Рынок недвижимости является основой рыночной экономики, поскольку представляет собой сферу вложений капитала в объекты недвижимости и систему экономических отношений, возникающих при операциях с недвижимостью. Одним из основных сегментов рынка недвижимости является рынок жилья, к объектам которого относят жилые дома и квартиры, их части, а также комнаты.
С появлением интернета процесс поиска недвижимости стал проще. Создание специальных сайтов позволяет ускорить процесс привлечения покупателей и снизить затраты продавцов на рекламу объекта недвижимости. Способом информирования покупателей о продаваемом объекте недвижимости является размещение объявлений на таких интернет-площадках.
В России насчитывается более 2,5 тысяч сайтов с объявлениями о продаже и аренде квартир. Яндекс.Недвижимость — крупнейший сервис поиска и подбора недвижимости в России с ежемесячной аудиторией более 4 миллионов человек. На сервисе собрана информация о продаже и сдаче в аренду комнат, квартир и домов на вторичном рынке, а также объявления о продаже недвижимости в новостройках, расположенных во всех регионах страны.
Приложение Яндекс.Недвижимость разработано с учётом поведенческих алгоритмов. Если человек замечен в подозрительной активности, его предложения будут проверены более тщательно. Автоматизированная система отследит аномалии и мошеннические действия. За счёт такой системы риски столкнуться с мошенником минимизируются.
В нашем распоряжении находятся данные сервиса Яндекс.Недвижимость: архив объявлений о продаже квартир в Санкт-Петербурге и других населённых пунктах Ленинградской области за несколько лет.
По каждой квартире на продажу доступны два вида данных. Первые внесены пользователем, вторые — получены автоматически на основе картографических данных. Например, расстояние до центра, аэропорта, ближайшего парка и водоёма.
Ключевой вопрос при купле-продажи квартиры — как определить её рыночную стоимость в конкретный момент времени. Рыночная стоимость — это цена, за которую объект может быть продан в условиях свободного рынка и с учётом конкуренции за период, соответствующий среднему сроку экспозиции. Рыночную цену жилья продавцу надо знать, чтобы не продешевить, а покупателю — чтобы не переплатить.
Цель исследования: выявить признаки, влияющие на конечную рыночную стоимость квартиры.
Задачи исследования:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
import sys
import os
import warnings
pd.set_option('display.max_columns', None)
np.set_printoptions(threshold=sys.maxsize)
warnings.filterwarnings('ignore')
Все данные хранятся в одном файле.
Файл данных real_estate_data.csv имеет формат CSV, в котором в качестве разделителя испольуется \t.
pth1 = r'C:\Users\Георгий\Documents\DS_projects\real_estate_data.csv'
pth2 = '/datasets/real_estate_data.csv'
pth3 = '/content/real_estate_data.csv'
if os.path.exists(pth1):
data = pd.read_csv(pth1, sep='\t')
elif os.path.exists(pth2):
data = pd.read_csv(pth2, sep='\t')
elif os.path.exists(pth3):
data = pd.read_csv(pth3, sep='\t')
else:
print('Something is wrong')
Убедимся, что данные подгрузились верно, без ошибок.
Для этого выведем первые 10 строк и последние 10 строк набора данных.
data.head(10)
| total_images | last_price | total_area | first_day_exposition | rooms | ceiling_height | floors_total | living_area | floor | is_apartment | studio | open_plan | kitchen_area | balcony | locality_name | airports_nearest | cityCenters_nearest | parks_around3000 | parks_nearest | ponds_around3000 | ponds_nearest | days_exposition | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 20 | 13000000.0 | 108.00 | 2019-03-07T00:00:00 | 3 | 2.70 | 16.0 | 51.00 | 8 | NaN | False | False | 25.00 | NaN | Санкт-Петербург | 18863.0 | 16028.0 | 1.0 | 482.0 | 2.0 | 755.0 | NaN |
| 1 | 7 | 3350000.0 | 40.40 | 2018-12-04T00:00:00 | 1 | NaN | 11.0 | 18.60 | 1 | NaN | False | False | 11.00 | 2.0 | посёлок Шушары | 12817.0 | 18603.0 | 0.0 | NaN | 0.0 | NaN | 81.0 |
| 2 | 10 | 5196000.0 | 56.00 | 2015-08-20T00:00:00 | 2 | NaN | 5.0 | 34.30 | 4 | NaN | False | False | 8.30 | 0.0 | Санкт-Петербург | 21741.0 | 13933.0 | 1.0 | 90.0 | 2.0 | 574.0 | 558.0 |
| 3 | 0 | 64900000.0 | 159.00 | 2015-07-24T00:00:00 | 3 | NaN | 14.0 | NaN | 9 | NaN | False | False | NaN | 0.0 | Санкт-Петербург | 28098.0 | 6800.0 | 2.0 | 84.0 | 3.0 | 234.0 | 424.0 |
| 4 | 2 | 10000000.0 | 100.00 | 2018-06-19T00:00:00 | 2 | 3.03 | 14.0 | 32.00 | 13 | NaN | False | False | 41.00 | NaN | Санкт-Петербург | 31856.0 | 8098.0 | 2.0 | 112.0 | 1.0 | 48.0 | 121.0 |
| 5 | 10 | 2890000.0 | 30.40 | 2018-09-10T00:00:00 | 1 | NaN | 12.0 | 14.40 | 5 | NaN | False | False | 9.10 | NaN | городской посёлок Янино-1 | NaN | NaN | NaN | NaN | NaN | NaN | 55.0 |
| 6 | 6 | 3700000.0 | 37.30 | 2017-11-02T00:00:00 | 1 | NaN | 26.0 | 10.60 | 6 | NaN | False | False | 14.40 | 1.0 | посёлок Парголово | 52996.0 | 19143.0 | 0.0 | NaN | 0.0 | NaN | 155.0 |
| 7 | 5 | 7915000.0 | 71.60 | 2019-04-18T00:00:00 | 2 | NaN | 24.0 | NaN | 22 | NaN | False | False | 18.90 | 2.0 | Санкт-Петербург | 23982.0 | 11634.0 | 0.0 | NaN | 0.0 | NaN | NaN |
| 8 | 20 | 2900000.0 | 33.16 | 2018-05-23T00:00:00 | 1 | NaN | 27.0 | 15.43 | 26 | NaN | False | False | 8.81 | NaN | посёлок Мурино | NaN | NaN | NaN | NaN | NaN | NaN | 189.0 |
| 9 | 18 | 5400000.0 | 61.00 | 2017-02-26T00:00:00 | 3 | 2.50 | 9.0 | 43.60 | 7 | NaN | False | False | 6.50 | 2.0 | Санкт-Петербург | 50898.0 | 15008.0 | 0.0 | NaN | 0.0 | NaN | 289.0 |
data.tail(10)
| total_images | last_price | total_area | first_day_exposition | rooms | ceiling_height | floors_total | living_area | floor | is_apartment | studio | open_plan | kitchen_area | balcony | locality_name | airports_nearest | cityCenters_nearest | parks_around3000 | parks_nearest | ponds_around3000 | ponds_nearest | days_exposition | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 23689 | 13 | 3550000.0 | 35.30 | 2018-02-28T00:00:00 | 1 | 2.86 | 15.0 | 16.3 | 4 | NaN | False | False | 9.10 | 2.0 | Санкт-Петербург | 17284.0 | 16081.0 | 1.0 | 353.0 | 2.0 | 652.0 | 29.0 |
| 23690 | 3 | 5500000.0 | 52.00 | 2018-07-19T00:00:00 | 2 | NaN | 5.0 | 31.0 | 2 | NaN | False | False | 6.00 | NaN | Санкт-Петербург | 20151.0 | 6263.0 | 1.0 | 300.0 | 0.0 | NaN | 15.0 |
| 23691 | 11 | 9470000.0 | 72.90 | 2016-10-13T00:00:00 | 2 | 2.75 | 25.0 | 40.3 | 7 | NaN | False | False | 10.60 | 1.0 | Санкт-Петербург | 19424.0 | 4489.0 | 0.0 | NaN | 1.0 | 806.0 | 519.0 |
| 23692 | 2 | 1350000.0 | 30.00 | 2017-07-07T00:00:00 | 1 | NaN | 5.0 | 17.5 | 4 | NaN | False | False | 6.00 | NaN | Тихвин | NaN | NaN | NaN | NaN | NaN | NaN | 413.0 |
| 23693 | 9 | 4600000.0 | 62.40 | 2016-08-05T00:00:00 | 3 | 2.60 | 9.0 | 40.0 | 8 | NaN | False | False | 8.00 | 0.0 | Петергоф | 45602.0 | 34104.0 | 1.0 | 352.0 | 1.0 | 675.0 | 239.0 |
| 23694 | 9 | 9700000.0 | 133.81 | 2017-03-21T00:00:00 | 3 | 3.70 | 5.0 | 73.3 | 3 | NaN | False | False | 13.83 | NaN | Санкт-Петербург | 24665.0 | 4232.0 | 1.0 | 796.0 | 3.0 | 381.0 | NaN |
| 23695 | 14 | 3100000.0 | 59.00 | 2018-01-15T00:00:00 | 3 | NaN | 5.0 | 38.0 | 4 | NaN | False | False | 8.50 | NaN | Тосно | NaN | NaN | NaN | NaN | NaN | NaN | 45.0 |
| 23696 | 18 | 2500000.0 | 56.70 | 2018-02-11T00:00:00 | 2 | NaN | 3.0 | 29.7 | 1 | NaN | False | False | NaN | NaN | село Рождествено | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 23697 | 13 | 11475000.0 | 76.75 | 2017-03-28T00:00:00 | 2 | 3.00 | 17.0 | NaN | 12 | NaN | False | False | 23.30 | 2.0 | Санкт-Петербург | 39140.0 | 10364.0 | 2.0 | 173.0 | 3.0 | 196.0 | 602.0 |
| 23698 | 4 | 1350000.0 | 32.30 | 2017-07-21T00:00:00 | 1 | 2.50 | 5.0 | 12.3 | 1 | NaN | False | False | 9.00 | NaN | поселок Новый Учхоз | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
Размер набора данных:
data.shape
(23699, 22)
Количество дубликатов в наименованиях признаков:
data.columns.duplicated().sum()
0
Уникальные наименования признаков:
data.columns.sort_values().tolist()
['airports_nearest', 'balcony', 'ceiling_height', 'cityCenters_nearest', 'days_exposition', 'first_day_exposition', 'floor', 'floors_total', 'is_apartment', 'kitchen_area', 'last_price', 'living_area', 'locality_name', 'open_plan', 'parks_around3000', 'parks_nearest', 'ponds_around3000', 'ponds_nearest', 'rooms', 'studio', 'total_area', 'total_images']
Количество элементов данных:
data.size
521378
Типы данных набора данных:
data.dtypes.value_counts()
float64 14 int64 3 object 3 bool 2 Name: count, dtype: int64
Пропущенные значения в данных:
data.isna().sum().sort_values()
total_images 0 open_plan 0 floor 0 rooms 0 studio 0 total_area 0 last_price 0 first_day_exposition 0 locality_name 49 floors_total 86 living_area 1903 kitchen_area 2278 days_exposition 3181 ponds_around3000 5518 parks_around3000 5518 cityCenters_nearest 5519 airports_nearest 5542 ceiling_height 9195 balcony 11519 ponds_nearest 14589 parks_nearest 15620 is_apartment 20924 dtype: int64
Распределение пропущенных значений в наборе данных:
sns.heatmap(data.isna(), cmap=sns.color_palette(['#000000', '#ffffff']))
plt.title('Тепловая карта\nраспределения пропущенных значений')
plt.xlabel('Название признака')
plt.ylabel('Номер записи')
plt.show()
Количество признаков без пропущенных значений:
(data.isna().sum() == 0).sum()
8
Общее количество пропущенных значений:
data.isna().sum().sum()
101441
Промежуточный вывод
Приведение названий столбцов к "змеиному_регистру":
data = data.rename(columns = {
'cityCenters_nearest': 'city_centers_nearest',
'parks_around3000': 'parks_around_3000',
'ponds_around3000': 'ponds_around_3000'
}
)
data.columns.unique().sort_values().to_list()
['airports_nearest', 'balcony', 'ceiling_height', 'city_centers_nearest', 'days_exposition', 'first_day_exposition', 'floor', 'floors_total', 'is_apartment', 'kitchen_area', 'last_price', 'living_area', 'locality_name', 'open_plan', 'parks_around_3000', 'parks_nearest', 'ponds_around_3000', 'ponds_nearest', 'rooms', 'studio', 'total_area', 'total_images']
Несмотря на то, что все данные были получены из двух источников: картографические данные собраны системой автоматически, а остальные данные введены пользователем вручную — по своему содержанию их можно разделить на несколько категорий.
Согласно Гражданскому кодексу РФ:
К недвижимым вещам (недвижимое имущество, недвижимость) относятся <...> здания...
Согласно Федеральному закону от 30.12.2009 г. № 384-ФЗ «Технический регламент о безопасности зданий и сооружений»:
Здание — результат строительства, представляющий собой объёмную строительную систему, имеющую надземную и (или) подземную части, включающую в себя помещения, сети инженерно-технического обеспечения и системы инженерно-технического обеспечения и предназначенную для проживания и (или) деятельности людей, размещения производства, хранения продукции или содержания животных.
Помещение — часть объёма здания или сооружения, имеющая определённое назначение и ограниченная строительными конструкциями.
Среди всех помещений Жилищный кодекс РФ выделяет жилые помещения:
Жилым помещением признается изолированное помещение, которое является недвижимым имуществом и пригодно для постоянного проживания граждан (отвечает установленным санитарным и техническим правилам и нормам, иным требованиям законодательства).
Причём все жилые помещения делятся на виды (ЖК РФ):
Жилым домом признается индивидуально-определённое здание, которое состоит из комнат, а также помещений вспомогательного использования, предназначенных для удовлетворения гражданами бытовых и иных нужд, связанных с их проживанием в таком здании.
Квартирой признается структурно обособленное помещение в многоквартирном доме, обеспечивающее возможность прямого доступа к помещениям общего пользования в таком доме и состоящее из одной или нескольких комнат, а также помещений вспомогательного использования, предназначенных для удовлетворения гражданами бытовых и иных нужд, связанных с их проживанием в таком обособленном помещении.
Комнатой признается часть жилого дома или квартиры, предназначенная для использования в качестве места непосредственного проживания граждан в жилом доме или квартире.
Кроме того, многоквартирное жилое здание (многоквартирный дом) определяется сводом правил
СП 54.13330.2022 "СНиП 31-01-2003 Здания жилые многоквартирные":
Здание жилое многоквартирное — жилое здание, включающее две и более квартиры, помещения общего пользования и общие инженерные системы.
*Характеристики объекта недвижимости*
Основными геометрическими параметрами являются площадь и высота помещения.
Площадь
total_area — общая площадь (м²)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
Согласно ЖК РФ:
Общая площадь жилого помещения состоит из суммы площади всех частей такого помещения, включая площадь помещений вспомогательного использования, предназначенных для удовлетворения гражданами бытовых и иных нужд, связанных с их проживанием в жилом помещении, за исключением балконов, лоджий, веранд и террас.
Таким образом, жилая площадь — это сумма площадей всех частей жилого помещения: в случае квартиры — сумма площадей всех комнат.
living_area — жилая площадь (м²)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
СП 54.13330.2022 "СНиП 31-01-2003 Здания жилые многоквартирные" даёт определение вспомогательного помещения:
Помещение вспомогательное — помещение квартиры для обеспечения коммуникационных, санитарных, технических и хозяйственно-бытовых нужд, в том числе: кухня (или кухня-столовая), передняя, внутриквартирные холл и коридор, ванная комната или душевая, уборная, туалет или совмещённый санузел, кладовая, постирочная, помещение теплогенераторной и т. п.
Кухня может быть реализована в виде отдельного помещения, либо отделена зона под неё.
Согласно СП 54.13330.2022 "СНиП 31-01-2003 Здания жилые многоквартирные":
Кухня — вспомогательное помещение с обеденной зоной, а также местом для размещения кухонного оборудования для приготовления пищи, мойки, хранения посуды и инвентаря.
Кухня-ниша — зона, предназначенная для приготовления пищи, расположенная смежно с жилым или вспомогательным помещением квартиры и оборудованная электрической плитой (электрическими варочной панелью и жарочным шкафом), мойкой и приточно-вытяжной вентиляцией с механическим или естественным побуждением.
kitchen_area — площадь кухни (м²)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
Таким образом, имеет место следующее соотношение:
$Общая\ площадь = Жилая\ площадь + Площадь\ вспомогательных\ помещений$
Получается, что
$Площадь\ кухни < Площадь\ помещений\ вспомогательного\ использования$.
Исключение могут составлять объявления о продажи изолированной комнаты или доли в квартире: в них может быть указано, что
$Жилая\ площадь = Общая\ площадь$.
И даже может случиться так, что
$Площадь\ кухни > Площадь\ остальных\ помещений\ вспомогательного\ использования$.
Высота
Высота помещения — это расстояние между полом и потолком. Однако на эту величину могут влиять напольное и потолочное покрытия, тем самым уменьшая её значение.
ceiling_height — высота потолков (м)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
Планировка
В каждом объекте недвижимости выделяют жилые комнаты или их не выделяют, а превращают все комнаты в одну большую квартиру-студию.
rooms — общее количество комнат в квартире
Признак является качественным, порядковым.
Шкала измерения признака: порядковая шкала.
По данным сервиса Яндекс.Недвижимость количество комнат:
при свободной планировке указывается по паспорту объекта;
не указывается для студий.
В нормативно-правовых актах РФ понятие "квартира-студия" не определено. Дом.рф даёт такое определение:
Квартира-студия представляет собой одно большое помещение, которое включает в себя комнату, кухню, прихожую. Отдельным помещением остаётся только санузел.
Квартира-студия может быть сформирована в результате перепланировки квартиры, либо изначально строится по проекту застройщика.
Юридически квартира-студия ничем не отличается от обычной квартиры.
studio — квартира-студия
Признак является категориальным, бинарным.
Шкала измерения признака: дихотомическая шкала.
По данным сервиса Яндекс.Недвижимость:
элемент не используется для объектов со свободной планировкой.
Если в квартире отсутствуют межкомнатные перекрытия, а пространство квартиры ограничено только внешними и межквартирными стенами, то говорят о свободной планировке квартиры.
Фактически, такие квартиры являются квартирами-студиями.
Юридически понятия "свободная планировка" не существует.
Основное достоинство квартир со свободной планировкой — открытое пространство. Свободная планировка предполагает возможности по изменению размеров комнат и их расположения.
open_plan — свободная планировка
Признак является категориальным, бинарным.
Шкала измерения признака: дихотомическая шкала.
По данным сервиса Яндекс.Недвижимость:
элемент не используется для студий.
Понятие балкона определяется в СП 54.13330.2022 "СНиП 31-01-2003 Здания жилые многоквартирные":
Балкон в жилом многоквартирном здании — выступающая из плоскости наружной стены ограждённая площадка, имеющая ограниченную глубину, взаимоувязанную с освещением примыкающего помещения; может выполняться с покрытием и остеклением.
Кроте того, существует ещё и французский балкон:
Балкон французский — световой проем, в который установлен балконный блок с внешним визуально проницаемым защитным ограждением.
balcony — количество балконов
Признак является качественным, порядковым.
Шкала измерения признака: порядковая шкала.
Балкон необходимо отличать от лоджии:
Лоджия — вспомогательное неотапливаемое помещение, встроенное в здание или пристроенное к нему, имеющее стены с трёх сторон (или с двух сторон при угловом расположении) на всю высоту этажа, ограждение с открытой стороны (сторон) и ограниченную глубину, взаимоувязанную с освещением помещения, к которому примыкает; может выполняться с покрытием и остеклением.
Расположение в здании
Согласно СП 54.13330.2022 "СНиП 31-01-2003 Здания жилые многоквартирные":
Этаж жилого многоквартирного здания — часть здания между высотными отметками верха перекрытия или пола по грунту и верха вышерасположенного перекрытия (покрытия), включающая пространство высотой в чистоте (от пола до потолка) 1,8 м и более, предназначенная для размещения помещений жилых, вспомогательных, общего пользования, общественного назначения, технических.
Этаж надземный в жилом многоквартирном здании — этаж с отметкой пола не ниже наиболее низкой планировочной отметки земли.
Этаж первый в жилом многоквартирном здании — этаж нижний надземный, доступный для входа с прилегающей территории.
Этаж подземный — этаж с отметкой пола ниже наиболее низкой планировочной отметки уровня земли на всю высоту помещений.
Этаж мансардный (мансарда) в жилом многоквартирном здании — этаж, фасад которого полностью или частично образован поверхностью (поверхностями) наклонной, ломаной или криволинейной крыши, при этом линия пересечения плоскости крыши и фасада должна быть на высоте не более 1,5 м от уровня пола мансардного этажа, в котором размещены жилые помещения, вспомогательные или помещения общественного назначения.
floor — этаж, на котором находится объект
Признак является качественным, порядковым.
Шкала измерения признака: порядковая шкала.
Особенности юридического статуса
Согласно СП 160.1325800.2014 "Здания и комплексы многофункциональные. Правила проектирования":
Апартаменты — жилые помещения, предназначенные для временного проживания, могут проектироваться в виде гостиничных номеров или квартирного типа для временного проживания (например, при сдаче внаём).
В настоящий момент правовой статус апартаментов не урегулирован. Поскольку Жилищный кодекс РФ не относит апартаменты к жилым помещениям, их относят к нежилым помещениям. Например, налогообложение апартаментов осуществляется в порядке, предусмотренном для нежилых помещений (Письмо Минфина РФ от 7.12.2020 г. N 03-05-04-01/106713). Кроме того, в апартаментах нельзя оформить постоянную регистрацию по месту жительства и пребывания.
is_apartment — апартаменты
Признак является категориальным, бинарным.
Шкала измерения признака: дихотомическая шкала.
*Характеристики здания*
Этажность здания
В соответствии с Инструкцией о проведении учёта жилищного фонда в Российской Федерации, утверждённой приказом Минземстроя от 04.08.98 N 37:
Этажность жилого дома должна определяться по числу надземных этажей.
При определении этажности в число надземных этажей включаются цокольные этажи, если верх перекрытия цокольного этажа возвышается над уровнем планировочной отметки земли не менее чем на 2 м.
Первым надземным считается этаж, пол которого находится не ниже уровня планировочной земли. Если отдельные части жилого дома имеют разное количество надземных этажей, его этажность определяется по наибольшему количеству этажей в здании.
В Письме Федерального агентства кадастра объектов недвижимости от 27 августа 2008 года N АМ/1567 "Об этажности жилого дома" отмечено, что под количеством этажей подразумевается "общее число этажей здания". Таким образом, этажность здания будет определяться как разность показателя "количество этажей" и показателя "количество подземных этажей".
floors_total — общее количество этажей в здании
Признак является качественным, порядковым.
Шкала измерения признака: порядковая шкала.
В сервисе Яндекс.Недвижимость под этим показателем подразумевается этажность здания.
Положение здания на местности
Населенный пункт — компактная территория совместного и постоянного или преимущественного проживания населения, имеющая сосредоточенную застройку в пределах установленной границы, официально получившая такой статус.
locality_name — название населённого пункта
Признак является категориальным, номинальным.
Шкала измерения признака: номинальная шкала.
Картографические данные взяты с сервиса Яндекс.Карты.
Сами дома на картах, их адреса, названия ЖК — указывают Яндекс Карты. Внести изменения в карты сервис Недвижимости не может.
Для измерения расстояний используется Линейка.
В Яндекс.Картах центр города Санкт-Петербурга расположен на Дворцовой площади возле Александровской колонны.
Расстояние между двумя точками — это длина отрезка, соединяющая эти точки. Однако сервис Яндекс.Карты позволяет также измерять расстояние по ломанной линии.
Измерить расстояние на карте можно по прямой или по ломаной линии, повторяя линии улиц.
Для понимания того, что из себя представляют расстояния в данных, можно провести эксперимент. Для этого необходимо измерить расстояние между центром Кронштадта и центром Санкт-Петербурга. Кронштадт — идеальный вариант для эксперимента: город расположен на острове в Финском заливе. Расстояние по прямой значительно отличается от расстояния, преодолеваемого по автомобильным дорогам. Если расстояние по прямо порядка 30 км, то расстояние по дороге порядка 50 км. Таким образом, все приведённые в наборе данные о расстоянии являются расстояниями, преодолеваемыми по автомобильным дорогам.
city_centers_nearest — расстояние до центра города Санкт-Петербурга (м)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
В Санкт-Петербурге три аэропорта:
Пассажирские рейсы по внутренним и международным направлениям обслуживает только аэропорт Пулково.
airports_nearest — расстояние до аэропорта Пулково (м)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
Парк — большой сад, роща с аллеями, цветниками, прудами и т. п.
В сервисе Яндекс.Карты контур парка либо совпадает с его административной границей, либо проводится в соответствии с ситуацией на местности (например, по забору).
parks_nearest — расстояние до ближайшего парка (м)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
parks_around_3000 — число парков в радиусе 3 км
Признак является качественным, порядковым.
Шкала измерения признака: порядковая шкала.
Водоём — место скопления воды.
В сервисе Яндекс.Карты это контурный гидрографический объект.
Контурные объекты — водоёмы (участки открытой водной поверхности: моря, заливы, гавани, проливы, озёра, водохранилища, пруды, акватории рек), ледники, болота, открытые бассейны.
ponds_nearest — расстояние до ближайшего водоёма (м)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
ponds_around_3000 — число водоёмов в радиусе 3 км
Признак является качественным, порядковым.
Шкала измерения признака: порядковая шкала.
Расстояния до парков и водоёмов — это расстояния, преодолеваемые пешком по пересечённой местности.
Экспериментально это можно установить, измерив расстояние от ЖК "Князь Александр Невский" до ближайшего водоёма — реки Невы.
*Характеристики объявления*
Хронометричекие данные
Дата публикации — дата подачи (создания) объявления.
К формату даты сервис Яндекс.Недвижимость предъявляет требование:
Все даты и время следует указывать согласно стандарту ISO 8601.
first_day_exposition — дата публикации
Признак является количественным, дискретным.
Шкала измерения признака: интервальная шкала.
Период (срок) размещения объявления — количество дней размещения объявления на сервисе от момента публикации до момента снятия с публикации.
days_exposition — период размещения объявления
Признак является количественным, дискретным.
Шкала измерения признака: шкала разностей.
Финансовые данные
Цена — стоимость объекта недвижимости, выраженная в рублях. Оплата стоимости объекта является условием сделки.
Цена за объект недвижимости является актуальной во время всего срока размещения объявления.
last_price — цена на момент снятия с публикации (руб.)
Признак является количественным, непрерывным.
Шкала измерения признака: шкала отношений.
Цена на момент снятия с публикации — целевой признак.
*Дополнительные данные*
Согласно требованиям сервиса Яндекс.Недвижимость фотографии объекта (в том числе планировок) являются обязательным элементом объявления.
total_images — количество фотографий квартиры в объявлении
Признак является качественным, порядковым.
Шкала измерения признака: порядковая шкала.
def graph(value):
'''
Функция строит диаграмму распределения значений и диаграмму размаха
исследуемых данных.
Принимает название признака исследуемого набора данных.
'''
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(15, 6))
ax1.set_title('Диаграмма распределения и диаграмма размаха' +
f'\nзначений признака {value}')
ax1.hist(data.loc[data[value].notna(), value], bins=100)
ax1.tick_params(labelbottom=False)
ax1.set_ylabel('Частота')
ax2.boxplot(data.loc[data[value].notna(), value], vert=False)
ax2.tick_params(left=False, labelleft=False)
ax2.set_xlabel(f'Значения признака {value}')
plt.show()
columns = ['last_price', 'total_area', 'living_area', 'kitchen_area',
'ceiling_height', 'city_centers_nearest', 'airports_nearest',
'parks_nearest', 'ponds_nearest', 'days_exposition']
data[columns].describe().round(2)
| last_price | total_area | living_area | kitchen_area | ceiling_height | city_centers_nearest | airports_nearest | parks_nearest | ponds_nearest | days_exposition | |
|---|---|---|---|---|---|---|---|---|---|---|
| count | 2.369900e+04 | 23699.00 | 21796.00 | 21421.00 | 14504.00 | 18180.00 | 18157.00 | 8079.00 | 9110.00 | 20518.00 |
| mean | 6.541549e+06 | 60.35 | 34.46 | 10.57 | 2.77 | 14191.28 | 28793.67 | 490.80 | 517.98 | 180.89 |
| std | 1.088701e+07 | 35.65 | 22.03 | 5.91 | 1.26 | 8608.39 | 12630.88 | 342.32 | 277.72 | 219.73 |
| min | 1.219000e+04 | 12.00 | 2.00 | 1.30 | 1.00 | 181.00 | 0.00 | 1.00 | 13.00 | 1.00 |
| 25% | 3.400000e+06 | 40.00 | 18.60 | 7.00 | 2.52 | 9238.00 | 18585.00 | 288.00 | 294.00 | 45.00 |
| 50% | 4.650000e+06 | 52.00 | 30.00 | 9.10 | 2.65 | 13098.50 | 26726.00 | 455.00 | 502.00 | 95.00 |
| 75% | 6.800000e+06 | 69.90 | 42.30 | 12.00 | 2.80 | 16293.00 | 37273.00 | 612.00 | 729.00 | 232.00 |
| max | 7.630000e+08 | 900.00 | 409.70 | 112.00 | 100.00 | 65968.00 | 84869.00 | 3190.00 | 1344.00 | 1580.00 |
for column in columns:
graph(column)
last_price — цена на момент снятия с публикации (руб.)
Значения определены для всех записей.
Значения определены с точностью до 1 руб.
Минимальное значение составляет 12 190 руб., максимальное — 763 млн руб.
Среднее арифметическое значение равно 6,54 млн руб., медиана — 4,65 млн руб.
Первый, второй и третий квартили — величины одного порядка (10$^6$ руб.). Не менее чем у половины объектов недвижимости значение стоимости попадает в диапазон 3—7 млн руб. Большое отличие среднего арифметического от медианы следует из того, что в выборке присутствуют объекты недвижимости, стоимость которых на 1—2 порядка выше (10$^7$—10$^8$ руб.). На диаграмме размаха эти значения не накрываются "ящиком с усами". Минимальное значение стоимости представляется сомнительным, поскольку оно меньше медианного значения на два порядка (10$^4$ руб.). Скорее всего, это свидетельствует о наличии ошибки в данных. Оценка распределения значений по гистограмме не представляется возможной из-за значительного размаха — в 4 порядка.
total_area — общая площадь (м²)
Значения определены для всех записей.
Значения определены с точностью до 0,01 м².
Минимальное значение составляет 12 м², максимальное — 900 м².
Среднее арифметическое значение равно 60,35 м², медиана — 52 м².
Первый, второй и третий квартили — близкие по значению величины. Не менее чем у половины объектов недвижимости значение общей площади попадает в диапазон 40—70 м². Наличие в выборке объектов недвижимости с большой общей площадью (более 200 м²) приводит к значительному отличию среднего арифметического от медианы. На диаграмме размаха эти значения не накрываются "ящиком с усами". По гистограмме можно охарактеризовать распределение значений как унимодальное с положительной ассиметрией пика.
living_area — жилая площадь (м²)
Значения определены для 21 796 записей — это 92 % всех записей.
Значения определены с точностью до 0,01 м².
Минимальное значение составляет 2 м², максимальное — 409,70 м².
Среднее арифметическое значение равно 34,46 м², медиана — 30 м².
Первый, второй и третий квартили — близкие по значению величины. Почти у половины объектов недвижимости значение жилой площади попадает в диапазон 18—43 м². Наличие в выборке объектов недвижимости с большой жилой площадью (более 100 м²) приводит к отличию среднего арифметического от медианы. На диаграмме размаха эти значения не накрываются "ящиком с усами". По гистограмме можно охарактеризовать распределение значений как бимодальное.
kitchen_area — площадь кухни (м²)
Значения определены для 21 421 записи — это 90 % всех записей.
Значения определены с точностью до 0,01 м².
Минимальное значение составляет 1,3 м², максимальное — 112 м².
Среднее арифметическое значение равно 10,57 м², медиана — 9,1 м².
Первый, второй и третий квартили — близкие по значению величины. Почти у половины объектов недвижимости значение площади кухни попадает в диапазон 7—12 м². Наличие в выборке объектов недвижимости с большой площадью кухни (более 20 м²) приводит к отличию среднего арифметического от медианы. На диаграмме размаха эти значения не накрываются "ящиком с усами". По гистограмме можно охарактеризовать распределение значений как унимодальное с положительной ассиметрией пика.
ceiling_height — высота потолков (м)
Значения определены для 14 504 записей — это 61 % всех записей.
Значения определены с точностью до 0,01 м.
Минимальное значение составляет 1 м, максимальное — 100 м.
Среднее арифметическое значение равно 2,77 м, медиана — 2,65 м.
Первый, второй и третий квартили — близкие по значению величины. Не менее чем у трети объектов недвижимости значение высоты потолков попадает в диапазон 2,5—2,8 м. На диаграмме размаха большинство значений накрываются "ящиком с усами". Но в выборке присутствуют значения меньше наблюдаемого минимума и больше наблюдаемого максимума. Минимальное и максимальное значения представляются сомнительными, что свидетельствует о наличии ошибок в данных. По гистограмме нельзя охарактеризовать распределение значений, поскольку пик распределения достаточно узкий и существуют значения, сильно отличающиеся от среднего. Узость "ящика с усами" на диаграмме размаха свидетельствует о низком разбросе значений относительно своего среднего.
city_centers_nearest — расстояние до центра города Санкт-Петербурга (м)
Значения определены для 18 180 записей — это 77 % всех записей.
Значения определены с точностью до 1 м.
Минимальное значение составляет 181 м, максимальное — 65 968 м.
Среднее арифметическое значение равно 14 191,28 м, медиана — 13 098,5 м.
Первый, второй и третий квартили — близкие по значению величины. Расстояние от объекта недвижимости до центра города Санкт-Петербурга в 40 % записей попадает в диапазон 9—17 км. На гистограмме наблюдается наличие нескольких максимумов. "Ящик с усами" на диаграмме размаха не накрывает значения больше 30 км.
airports_nearest — расстояние до аэропорта Пулково (м)
Значения определены для 18 157 записей — это 77 % всех записей.
Значения определены с точностью до 1 м.
Минимальное значение составляет 0 м, максимальное — 84 869 м.
Среднее арифметическое значение равно 28 793,67 м, медиана — 26 726 м.
Первый, второй и третий квартили различаются между собой на 9 км. На гистограмме видно, что распределение значений широкое, с несколькими максимумами. На диаграмме размаха также наблюдается увеличенная ширина "ящика" с увеличенной длиной "усов". "Ящик с усами" не накрывает значения больше 70 км. Минимальное значение 0 м представляется сомнительным. Это свидетельствует о наличии ошибки в данных.
parks_nearest — расстояние до ближайшего парка (м)
Значения определены для 8079 записей — это 34 % всех записей.
Значения определены с точностью до 1 м.
Минимальное значение составляет 1 м, максимальное — 3190 м.
Среднее арифметическое значение равно 490,8 м, медиана — 455 м.
Первый, второй и третий квартили — близкие по значению величины. Расстояние от объекта недвижимости до ближайшего парка не менее чем в 15 % записей попадает в диапазон 280—620 м. Наличие в выборке объектов недвижимости, от которых до парка более 1200 м приводит к смещению среднего арифметического от медианы в большую сторону. Эти значения не накрываются "ящиком с усами" на диаграмме размаха. По гистограмме можно охарактеризовать распределение значений как унимодальное с практически отсутствующей ассиметрией пика. Минимальное значение 1 м представляется сомнительным. Это свидетельствует о наличии ошибки в данных.
ponds_nearest — расстояние до ближайшего водоёма (м)
Значения определены для 9110 записей — это 38 % всех записей.
Значения определены с точностью до 1 м.
Минимальное значение составляет 13 м, максимальное — 1344 м.
Среднее арифметическое значение равно 517,98 м, медиана — 502 м.
Первый, второй и третий квартили различаются между собой на 200 м. Среднее арифметическое совсем незначительно отличается от медианы. На гистограмме видно, что распределение значений широкое, с единственным максимумом. Все значения накрываются "ящиком с усами" на диаграмме размаха.
days_exposition — период размещения объявления
Значения определены для 20 518 записей — это 87 % всех записей.
Значения определены с точностью до 1 дня.
Минимальное значение составляет 1 день, максимальное — 1580 дней.
Медиана — 95 дней. Среднее арифметическое — 181 день.
Среднее арифметическое значительно отличается от медианы. Это является следствием наличия сильно отличающихся, больших значений в выборке. Третий квартиль сильнее отличается от медианы, чем первый квартиль. По гистограмме можно охарактеризовать распределение значений как экспоненциальное. На диаграмме размаха "ящик с усами" не накрывает значения больше 600 дней.
columns = ['rooms', 'balcony', 'floor', 'floors_total',
'parks_around_3000', 'ponds_around_3000', 'total_images']
data[columns].describe().round(2)
| rooms | balcony | floor | floors_total | parks_around_3000 | ponds_around_3000 | total_images | |
|---|---|---|---|---|---|---|---|
| count | 23699.00 | 12180.00 | 23699.00 | 23613.00 | 18181.00 | 18181.00 | 23699.00 |
| mean | 2.07 | 1.15 | 5.89 | 10.67 | 0.61 | 0.77 | 9.86 |
| std | 1.08 | 1.07 | 4.89 | 6.60 | 0.80 | 0.94 | 5.68 |
| min | 0.00 | 0.00 | 1.00 | 1.00 | 0.00 | 0.00 | 0.00 |
| 25% | 1.00 | 0.00 | 2.00 | 5.00 | 0.00 | 0.00 | 6.00 |
| 50% | 2.00 | 1.00 | 4.00 | 9.00 | 0.00 | 1.00 | 9.00 |
| 75% | 3.00 | 2.00 | 8.00 | 16.00 | 1.00 | 1.00 | 14.00 |
| max | 19.00 | 5.00 | 33.00 | 60.00 | 3.00 | 3.00 | 50.00 |
for column in columns:
graph(column)
rooms — общее количество комнат в квартире
Значения определены для всех записей.
Разница между уровнями значений — 1 комната.
Минимальное значение составляет 0 комнат, максимальное — 19 комнат.
Медиана — 2 комнаты.
Первый, второй и третий квартили — близкие по значению величины. Не менее чем у половины объектов недвижимости значение количества комнат находится в диапазоне 1—3. Большинство объектов недвижимости имеет не более 7 комнат — эти значения накрываются "ящиком с усами" на диаграмме размаха.
balcony — количество балконов
Значения определены для 12 180 записей — это 51 % всех записей.
Разница между уровнями значений — 1 балкон.
Минимальное значение составляет 0 балконов, максимальное — 5 балконов.
Медиана — 1 балкон.
Первый, второй и третий квартили — близкие по значению величины. Большинство объектов недвижимости имеет не более 2 балконов — это отчётливо видно на гистограмме.
floor — этаж, на котором находится объект
Значения определены для всех записей.
Разница между уровнями значений — 1 этаж.
Минимальное значение — 1-й этаж, максимальное — 33-й этаж.
Медиана — 4-й этаж.
Не менее половины всех объектов недвижимости расположены на этаже из диапазона 2—8-й этаж. Большинство объектов расположено не выше 17-го этажа — эти значения накрывает "ящик с усами" на диаграмме размаха.
floors_total — общее количество этажей в здании
Значения определены для 23 613 записей — это 99,6 % записей.
Разница между уровнями значений — 1 этаж.
Минимальное значение составляет 1 этаж, максимальное — 60 этажей.
Медиана — 9 этажей.
Не менее половины всех объектов недвижимости расположены в зданиях, этажность которых находится в диапазоне 5—16 этажей. Большинство всех зданий имеют этажность менее 30 этажей — эти значения накрывает "ящик с усами" на диаграмме размаха.
parks_around_3000 — число парков в радиусе 3 км
Значения определены для 18 181 записи — это 77 % записей.
Разница между уровнями значений — 1 парк.
Минимальное значение составляет 0 парков, максимальное — 3 парка.
Медиана — 0 парков.
ponds_around_3000 — число водоёмов в радиусе 3 км
Значения определены для 18 181 записи — это 77 % записей.
Разница между уровнями значений — 1 водоём.
Минимальное значение составляет 0 водоёмов, максимальное — 3 водоёма.
Медиана — 1 водоём.
total_images — количество фотографий квартиры в объявлении
Значения определены для всех записей.
Разница между уровнями значений — 1 фотография.
Минимальное значение составляет 0 фотографий, максимальное — 50 фотографий.
Медиана — 9 фотографий.
Первый, второй и третий квартили — близкие по значению величины. Не менее половины всех объектов недвижимости публикуются с фотографиями, количество которых находится в диапазоне 6—14 фотографий. В большинстве объявлений количество опубликованных фотографий не превышает 20.
data[['first_day_exposition', 'locality_name',
'studio', 'open_plan', 'is_apartment']].describe()
| first_day_exposition | locality_name | studio | open_plan | is_apartment | |
|---|---|---|---|---|---|
| count | 23699 | 23650 | 23699 | 23699 | 2775 |
| unique | 1491 | 364 | 2 | 2 | 2 |
| top | 2018-02-01T00:00:00 | Санкт-Петербург | False | False | False |
| freq | 368 | 15721 | 23550 | 23632 | 2725 |
data['first_day_exposition'].value_counts().head()
first_day_exposition 2018-02-01T00:00:00 368 2017-11-10T00:00:00 240 2017-10-13T00:00:00 124 2017-09-27T00:00:00 111 2018-03-26T00:00:00 97 Name: count, dtype: int64
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(15, 6))
ax1.set_title('Диаграмма распределения и диаграмма размаха' +
'\nколичества уникальных значений признака first_day_exposition')
ax1.hist(data['first_day_exposition'].value_counts(), bins=100)
ax1.tick_params(labelbottom=False)
ax1.set_ylabel('Частота')
ax2.boxplot(data['first_day_exposition'].value_counts(), vert=False)
ax2.tick_params(left=False, labelleft=False)
ax2.set_xlabel('Количество уникальных значений признака first_day_exposition')
plt.show()
first_day_exposition — дата публикации
Значения определены для всех записей.
Мода — 1 февраля 2018 года, её частота — 368.
Минимальное число публикаций в день — 1, максимальное — 368. За наблюдаемый период времени для большинства дней количество публикуемых объявлений в день не превышало 50.
data['locality_name'].value_counts().head()
locality_name Санкт-Петербург 15721 посёлок Мурино 522 посёлок Шушары 440 Всеволожск 398 Пушкин 369 Name: count, dtype: int64
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(15, 6))
ax1.set_title('Диаграмма распределения и диаграмма размаха' +
'\nколичества уникальных значений признака locality_name')
ax1.hist(data['locality_name'].value_counts(), bins=100)
ax1.tick_params(labelbottom=False)
ax1.set_ylabel('Частота')
ax2.boxplot(data['locality_name'].value_counts(), vert=False)
ax2.tick_params(left=False, labelleft=False)
ax2.set_xlabel('Количество уникальных значений признака locality_name')
plt.show()
locality_name — название населённого пункта
Значения определены для 23 650 записей — это 99,8 % всех записей.
Мода — город Санкт-Петербург, её частота — 15 721.
Минимальное количество объявлений, приходящихся на один населённый пункт, — 1, максимальное — 15 721.
В большинстве населённых пунктах расположено по 1 объекту недвижимости, объявления о которых были размещены на сервисе.
columns = ['studio', 'open_plan', 'is_apartment']
for column in columns:
plt.figure(figsize=(5, 3))
plt.title(f'Гистограма распределения\nзначений признака {column}')
data[column].value_counts().plot(kind='bar', rot=0)
plt.xlabel(f'Значения признака {column}')
plt.ylabel('Частота')
plt.show()
studio — квартира-студия
Значения определены для всех записей.
Мода — объект недвижимости не является квартирой-студией, её частота — 23 550.
open_plan — открытая планировка
Значения определены для всех записей.
Мода — в объекте недвижимости нет открытой планировки, её частота — 23 632.
is_apartment — апартаменты
Значения определены для 2775 записей — это 12 % всех записей.
Мода — объект недвижимости не является апартаментами, её частота — 2725.
Промежуточный вывод
Прежде всего произведём обработку текстовых значений.
Признак locality_name содержит в своих значениях вложенные сведения: в них указаны не только наименования населённых пунктов, но и их тип. Населённые пункты, для которых не указан в явном виде тип, относятся к типу "город".
data['locality_name'].sort_values().unique()
array(['Бокситогорск', 'Волосово', 'Волхов', 'Всеволожск', 'Выборг',
'Высоцк', 'Гатчина', 'Зеленогорск', 'Ивангород', 'Каменногорск',
'Кингисепп', 'Кириши', 'Кировск', 'Колпино', 'Коммунар',
'Красное Село', 'Кронштадт', 'Кудрово', 'Лодейное Поле',
'Ломоносов', 'Луга', 'Любань', 'Мурино', 'Никольское',
'Новая Ладога', 'Отрадное', 'Павловск', 'Петергоф', 'Пикалёво',
'Подпорожье', 'Приморск', 'Приозерск', 'Пушкин', 'Санкт-Петербург',
'Светогорск', 'Сертолово', 'Сестрорецк', 'Сланцы', 'Сосновый Бор',
'Сясьстрой', 'Тихвин', 'Тосно', 'Шлиссельбург',
'городской поселок Большая Ижора', 'городской поселок Янино-1',
'городской посёлок Будогощь', 'городской посёлок Виллози',
'городской посёлок Лесогорский', 'городской посёлок Мга',
'городской посёлок Назия', 'городской посёлок Новоселье',
'городской посёлок Павлово', 'городской посёлок Рощино',
'городской посёлок Свирьстрой', 'городской посёлок Советский',
'городской посёлок Фёдоровское', 'городской посёлок Янино-1',
'деревня Агалатово', 'деревня Аро', 'деревня Батово',
'деревня Бегуницы', 'деревня Белогорка', 'деревня Большая Вруда',
'деревня Большая Пустомержа', 'деревня Большие Колпаны',
'деревня Большое Рейзино', 'деревня Большой Сабск', 'деревня Бор',
'деревня Борисова Грива', 'деревня Ваганово', 'деревня Вартемяги',
'деревня Вахнова Кара', 'деревня Выскатка', 'деревня Гарболово',
'деревня Глинка', 'деревня Горбунки', 'деревня Гостилицы',
'деревня Заклинье', 'деревня Заневка', 'деревня Зимитицы',
'деревня Извара', 'деревня Иссад', 'деревня Калитино',
'деревня Кальтино', 'деревня Камышовка', 'деревня Каськово',
'деревня Келози', 'деревня Кипень', 'деревня Кисельня',
'деревня Колтуши', 'деревня Коркино', 'деревня Котлы',
'деревня Кривко', 'деревня Кудрово', 'деревня Кузьмолово',
'деревня Курковицы', 'деревня Куровицы', 'деревня Куттузи',
'деревня Лаврики', 'деревня Лаголово', 'деревня Лампово',
'деревня Лесколово', 'деревня Лопухинка', 'деревня Лупполово',
'деревня Малая Романовка', 'деревня Малое Верево',
'деревня Малое Карлино', 'деревня Малые Колпаны',
'деревня Мануйлово', 'деревня Меньково', 'деревня Мины',
'деревня Мистолово', 'деревня Ненимяки', 'деревня Нижние Осельки',
'деревня Нижняя', 'деревня Низино', 'деревня Новое Девяткино',
'деревня Новолисино', 'деревня Нурма', 'деревня Оржицы',
'деревня Парицы', 'деревня Пельгора', 'деревня Пеники',
'деревня Пижма', 'деревня Пикколово', 'деревня Пудомяги',
'деревня Пустынка', 'деревня Пчева', 'деревня Рабитицы',
'деревня Разбегаево', 'деревня Раздолье', 'деревня Разметелево',
'деревня Рапполово', 'деревня Реброво', 'деревня Русско',
'деревня Сижно', 'деревня Снегирёвка', 'деревня Старая',
'деревня Старая Пустошь', 'деревня Старое Хинколово',
'деревня Старополье', 'деревня Старосиверская',
'деревня Старые Бегуницы', 'деревня Суоранда',
'деревня Сяськелево', 'деревня Тарасово', 'деревня Терпилицы',
'деревня Тихковицы', 'деревня Тойворово', 'деревня Торосово',
'деревня Торошковичи', 'деревня Трубников Бор',
'деревня Фалилеево', 'деревня Фёдоровское', 'деревня Хапо-Ое',
'деревня Хязельки', 'деревня Чудской Бор', 'деревня Шпаньково',
'деревня Щеглово', 'деревня Юкки', 'деревня Ялгино',
'деревня Яльгелево', 'деревня Ям-Тесово',
'коттеджный поселок Кивеннапа Север', 'коттеджный поселок Счастье',
'коттеджный посёлок Лесное', 'поселок Аннино', 'поселок Барышево',
'поселок Бугры', 'поселок Возрождение', 'поселок Войсковицы',
'поселок Володарское', 'поселок Гаврилово', 'поселок Гарболово',
'поселок Гладкое', 'поселок Глажево', 'поселок Глебычево',
'поселок Гончарово', 'поселок Громово', 'поселок Дружноселье',
'поселок Елизаветино', 'поселок Жилгородок', 'поселок Жилпосёлок',
'поселок Житково', 'поселок Заводской', 'поселок Запорожское',
'поселок Зимитицы', 'поселок Ильичёво', 'поселок Калитино',
'поселок Каложицы', 'поселок Кингисеппский', 'поселок Кирпичное',
'поселок Кобралово', 'поселок Кобринское', 'поселок Коммунары',
'поселок Коробицыно', 'поселок Котельский',
'поселок Красная Долина', 'поселок Красносельское',
'поселок Лесное', 'поселок Лисий Нос', 'поселок Лукаши',
'поселок Любань', 'поселок Мельниково', 'поселок Мичуринское',
'поселок Молодцово', 'поселок Мурино', 'поселок Новый Свет',
'поселок Новый Учхоз', 'поселок Оредеж',
'поселок Пансионат Зелёный Бор', 'поселок Первомайское',
'поселок Перово', 'поселок Петровское', 'поселок Победа',
'поселок Поляны', 'поселок Почап', 'поселок Починок',
'поселок Пушное', 'поселок Пчевжа', 'поселок Рабитицы',
'поселок Романовка', 'поселок Ромашки', 'поселок Рябово',
'поселок Севастьяново', 'поселок Селезнёво', 'поселок Сельцо',
'поселок Семиозерье', 'поселок Семрино', 'поселок Серебрянский',
'поселок Совхозный', 'поселок Старая Малукса',
'поселок Стеклянный', 'поселок Сумино', 'поселок Суходолье',
'поселок Тельмана', 'поселок Терволово', 'поселок Торковичи',
'поселок Тёсово-4', 'поселок Углово', 'поселок Усть-Луга',
'поселок Ушаки', 'поселок Цвелодубово', 'поселок Цвылёво',
'поселок городского типа Большая Ижора',
'поселок городского типа Вырица',
'поселок городского типа Дружная Горка',
'поселок городского типа Дубровка',
'поселок городского типа Ефимовский',
'поселок городского типа Кондратьево',
'поселок городского типа Красный Бор',
'поселок городского типа Кузьмоловский',
'поселок городского типа Лебяжье',
'поселок городского типа Лесогорский',
'поселок городского типа Назия',
'поселок городского типа Никольский',
'поселок городского типа Приладожский',
'поселок городского типа Рахья', 'поселок городского типа Рощино',
'поселок городского типа Рябово',
'поселок городского типа Синявино',
'поселок городского типа Советский',
'поселок городского типа Токсово',
'поселок городского типа Форносово',
'поселок городского типа имени Свердлова',
'поселок станции Вещево', 'поселок станции Корнево',
'поселок станции Лужайка', 'поселок станции Приветнинское',
'посёлок Александровская', 'посёлок Алексеевка', 'посёлок Аннино',
'посёлок Белоостров', 'посёлок Бугры', 'посёлок Возрождение',
'посёлок Войскорово', 'посёлок Высокоключевой',
'посёлок Гаврилово', 'посёлок Дзержинского', 'посёлок Жилгородок',
'посёлок Ильичёво', 'посёлок Кикерино', 'посёлок Кобралово',
'посёлок Коробицыно', 'посёлок Левашово', 'посёлок Ленинское',
'посёлок Лисий Нос', 'посёлок Мельниково', 'посёлок Металлострой',
'посёлок Мичуринское', 'посёлок Молодёжное', 'посёлок Мурино',
'посёлок Мыза-Ивановка', 'посёлок Новогорелово',
'посёлок Новый Свет', 'посёлок Пансионат Зелёный Бор',
'посёлок Парголово', 'посёлок Перово', 'посёлок Песочный',
'посёлок Петро-Славянка', 'посёлок Петровское',
'посёлок Платформа 69-й километр', 'посёлок Плодовое',
'посёлок Плоское', 'посёлок Победа', 'посёлок Поляны',
'посёлок Понтонный', 'посёлок Пригородный', 'посёлок Пудость',
'посёлок Репино', 'посёлок Ропша', 'посёлок Сапёрное',
'посёлок Сапёрный', 'посёлок Сосново', 'посёлок Старая Малукса',
'посёлок Стеклянный', 'посёлок Стрельна', 'посёлок Суйда',
'посёлок Сумино', 'посёлок Тельмана', 'посёлок Терволово',
'посёлок Торфяное', 'посёлок Усть-Ижора', 'посёлок Усть-Луга',
'посёлок Форт Красная Горка', 'посёлок Шугозеро', 'посёлок Шушары',
'посёлок Щеглово', 'посёлок городского типа Важины',
'посёлок городского типа Вознесенье',
'посёлок городского типа Вырица',
'посёлок городского типа Красный Бор',
'посёлок городского типа Кузнечное',
'посёлок городского типа Кузьмоловский',
'посёлок городского типа Лебяжье', 'посёлок городского типа Мга',
'посёлок городского типа Павлово',
'посёлок городского типа Рощино', 'посёлок городского типа Рябово',
'посёлок городского типа Сиверский',
'посёлок городского типа Тайцы', 'посёлок городского типа Токсово',
'посёлок городского типа Ульяновка',
'посёлок городского типа Форносово',
'посёлок городского типа имени Морозова',
'посёлок городского типа имени Свердлова',
'посёлок при железнодорожной станции Вещево',
'посёлок при железнодорожной станции Приветнинское',
'посёлок станции Громово', 'посёлок станции Свирь',
'садоводческое некоммерческое товарищество Лесная Поляна',
'садовое товарищество Новая Ропша',
'садовое товарищество Приладожский', 'садовое товарищество Рахья',
'садовое товарищество Садко', 'село Копорье', 'село Никольское',
'село Павлово', 'село Паша', 'село Путилово', 'село Рождествено',
'село Русско-Высоцкое', 'село Старая Ладога', 'село Шум', nan],
dtype=object)
В обозначениях типа населённого пункта встречаются слова, различающиеся буквами е и ё. Необходимо привести названия типов населённых пунктов к единому формату, а затем выделить их в отдельный признак — locality_type.
# Корректировка текстовых значений.
data['locality_name'] = data['locality_name'].replace('поселок', 'посёлок', regex=True)
# Названия типов населённых пунктов.
locality_type = ['посёлок',
'посёлок городского типа',
'городской посёлок',
'посёлок при железнодорожной станции',
'посёлок станции',
'коттеджный посёлок',
'деревня',
'село',
'садоводческое некоммерческое товарищество',
'садовое товарищество']
# Извлечение названия типа населённого пункта из значений признака locality_name.
for i in data[data['locality_name'].notna()].index:
for j in range(len(locality_type)):
if locality_type[j] in data.loc[i, 'locality_name']:
data.loc[i, 'locality_type'] = locality_type[j]
# Присвоение значения 'город' в качестве типа населённого пункта для тех записей,
# у которых в значениях признака locality_name тип не указан в явном виде.
for i in data[data['locality_name'].notna() & data['locality_type'].isna()].index:
data.loc[i, 'locality_type'] = 'город'
data[['locality_name', 'locality_type']].sample(7)
| locality_name | locality_type | |
|---|---|---|
| 20529 | Санкт-Петербург | город |
| 20467 | Кудрово | город |
| 2804 | деревня Кудрово | деревня |
| 27 | Санкт-Петербург | город |
| 899 | деревня Кудрово | деревня |
| 13227 | Всеволожск | город |
| 4046 | Санкт-Петербург | город |
data['locality_type'].unique()
array(['город', 'посёлок', 'городской посёлок', 'деревня',
'посёлок городского типа', 'садовое товарищество', 'село', nan,
'посёлок станции', 'садоводческое некоммерческое товарищество',
'посёлок при железнодорожной станции', 'коттеджный посёлок'],
dtype=object)
Взаимно однозначное соответствие между значениями признака locality_type и значениями признака locality_name установлено верно. Список уникальных значений содержит только те названия типов, которые были заданы. Поскольку признак locality_name содержит пропуски, то и признак locality_type содержит пропуски в тех же записях.
В соответствии с законом "Об административно-территориальном устройстве Ленинградской области и порядке его изменения" наименования "городской посёлок" и "посёлок городского типа" являются синонимами. Кроме того, в соответствии с законом "посёлок станции" именуется как "посёлок при железнодорожной станции".
Заменим "посёлок городского типа" на "городской посёлок", а "посёлок станции" на "посёлок при железнодорожной станции".
data.loc[data['locality_type'] == 'посёлок городского типа',
'locality_type'] = 'городской посёлок'
data.loc[data['locality_type'] == 'посёлок станции',
'locality_type'] = 'посёлок при железнодорожной станции'
data['locality_type'].sort_values().unique()
array(['город', 'городской посёлок', 'деревня', 'коттеджный посёлок',
'посёлок', 'посёлок при железнодорожной станции',
'садоводческое некоммерческое товарищество',
'садовое товарищество', 'село', nan], dtype=object)
Теперь уберём наиманование типа населённого пункта из признака locality_name.
locality_type = ['посёлок городского типа',
'городской посёлок',
'посёлок при железнодорожной станции',
'посёлок станции',
'коттеджный посёлок',
'посёлок',
'деревня',
'село',
'садоводческое некоммерческое товарищество',
'садовое товарищество']
for type_name in locality_type:
data['locality_name'] = data['locality_name'].replace(type_name, '',
regex=True).str.strip()
sorted(data[data['locality_name'].notna()]['locality_name'].unique())
['Агалатово', 'Александровская', 'Алексеевка', 'Аннино', 'Аро', 'Барышево', 'Батово', 'Бегуницы', 'Белогорка', 'Белоостров', 'Бокситогорск', 'Большая Вруда', 'Большая Ижора', 'Большая Пустомержа', 'Большие Колпаны', 'Большое Рейзино', 'Большой Сабск', 'Бор', 'Борисова Грива', 'Бугры', 'Будогощь', 'Ваганово', 'Важины', 'Вартемяги', 'Вахнова Кара', 'Вещево', 'Виллози', 'Вознесенье', 'Возрождение', 'Войсковицы', 'Войскорово', 'Володарское', 'Волосово', 'Волхов', 'Всеволожск', 'Выборг', 'Вырица', 'Выскатка', 'Высокоключевой', 'Высоцк', 'Гаврилово', 'Гарболово', 'Гатчина', 'Гладкое', 'Глажево', 'Глебычево', 'Глинка', 'Гончарово', 'Горбунки', 'Гостилицы', 'Громово', 'Дзержинского', 'Дружная Горка', 'Дружноселье', 'Дубровка', 'Елизаветино', 'Ефимовский', 'Жил', 'Жилгородок', 'Житково', 'Заводской', 'Заклинье', 'Заневка', 'Запорожское', 'Зеленогорск', 'Зимитицы', 'Ивангород', 'Извара', 'Ильичёво', 'Иссад', 'Калитино', 'Каложицы', 'Кальтино', 'Каменногорск', 'Камышовка', 'Каськово', 'Келози', 'Кивеннапа Север', 'Кикерино', 'Кингисепп', 'Кингисеппский', 'Кипень', 'Кириши', 'Кировск', 'Кирпичное', 'Кисельня', 'Кобралово', 'Кобринское', 'Колпино', 'Колтуши', 'Коммунар', 'Коммунары', 'Кондратьево', 'Копорье', 'Коркино', 'Корнево', 'Коробицыно', 'Котельский', 'Котлы', 'Красная Долина', 'Красное Село', 'Красносельское', 'Красный Бор', 'Кривко', 'Кронштадт', 'Кудрово', 'Кузнечное', 'Кузьмолово', 'Кузьмоловский', 'Курковицы', 'Куровицы', 'Куттузи', 'Лаврики', 'Лаголово', 'Лампово', 'Лебяжье', 'Левашово', 'Ленинское', 'Лесколово', 'Лесная Поляна', 'Лесное', 'Лесогорский', 'Лисий Нос', 'Лодейное Поле', 'Ломоносов', 'Лопухинка', 'Луга', 'Лужайка', 'Лукаши', 'Лупполово', 'Любань', 'Малая Романовка', 'Малое Верево', 'Малое Карлино', 'Малые Колпаны', 'Мануйлово', 'Мга', 'Мельниково', 'Меньково', 'Металлострой', 'Мины', 'Мистолово', 'Мичуринское', 'Молодцово', 'Молодёжное', 'Мурино', 'Мыза-Ивановка', 'Назия', 'Ненимяки', 'Нижние Осельки', 'Нижняя', 'Низино', 'Никольский', 'Никольское', 'Новая Ладога', 'Новая Ропша', 'Новогорелово', 'Новое Девяткино', 'Новолисино', 'Новоселье', 'Новый Свет', 'Новый Учхоз', 'Нурма', 'Оредеж', 'Оржицы', 'Отрадное', 'Павлово', 'Павловск', 'Пансионат Зелёный Бор', 'Парголово', 'Парицы', 'Паша', 'Пельгора', 'Пеники', 'Первомайское', 'Перово', 'Песочный', 'Петергоф', 'Петро-Славянка', 'Петровское', 'Пижма', 'Пикалёво', 'Пикколово', 'Платформа 69-й километр', 'Плодовое', 'Плоское', 'Победа', 'Подпорожье', 'Поляны', 'Понтонный', 'Почап', 'Починок', 'Приветнинское', 'Пригородный', 'Приладожский', 'Приморск', 'Приозерск', 'Пудомяги', 'Пудость', 'Пустынка', 'Путилово', 'Пушкин', 'Пушное', 'Пчева', 'Пчевжа', 'Рабитицы', 'Разбегаево', 'Раздолье', 'Разметелево', 'Рапполово', 'Рахья', 'Реброво', 'Репино', 'Рождествено', 'Романовка', 'Ромашки', 'Ропша', 'Рощино', 'Русско', 'Русско-Высоцкое', 'Рябово', 'Садко', 'Санкт-Петербург', 'Сапёрное', 'Сапёрный', 'Светогорск', 'Свирь', 'Свирьстрой', 'Севастьяново', 'Селезнёво', 'Сельцо', 'Семиозерье', 'Семрино', 'Серебрянский', 'Сертолово', 'Сестрорецк', 'Сиверский', 'Сижно', 'Синявино', 'Сланцы', 'Снегирёвка', 'Советский', 'Совхозный', 'Сосново', 'Сосновый Бор', 'Старая', 'Старая Ладога', 'Старая Малукса', 'Старая Пустошь', 'Старое Хинколово', 'Старополье', 'Старосиверская', 'Старые Бегуницы', 'Стеклянный', 'Стрельна', 'Суйда', 'Сумино', 'Суоранда', 'Суходолье', 'Счастье', 'Сяськелево', 'Сясьстрой', 'Тайцы', 'Тарасово', 'Тельмана', 'Терволово', 'Терпилицы', 'Тихвин', 'Тихковицы', 'Тойворово', 'Токсово', 'Торковичи', 'Торосово', 'Торошковичи', 'Торфяное', 'Тосно', 'Трубников Бор', 'Тёсово-4', 'Углово', 'Ульяновка', 'Усть-Ижора', 'Усть-Луга', 'Ушаки', 'Фалилеево', 'Форносово', 'Форт Красная Горка', 'Фёдоровское', 'Хапо-Ое', 'Хязельки', 'Цвелодубово', 'Цвылёво', 'Чудской Бор', 'Шлиссельбург', 'Шпаньково', 'Шугозеро', 'Шум', 'Шушары', 'Щеглово', 'Юкки', 'Ялгино', 'Яльгелево', 'Ям-Тесово', 'Янино-1', 'имени Морозова', 'имени Свердлова']
Тип населённого пункта "коттеджный посёлок" отсутствует в российском законодательстве. Коттеджный посёлок Кивеннапа Север является частью посёлка Первомайское. Коттеджные посёлки Счастье и Лесное встречаются в Ленинградской области более одного раза. Установить однозначно их местоположение не представляется возможным. Поэтому записи об объектах в этих посёлках удаляем.
data.loc[data['locality_name'] == 'Кивеннапа Север',
['locality_name', 'locality_type']] = ['Первомайское', 'посёлок']
data.drop(index=data[data['locality_type'] == 'коттеджный посёлок'].index,
inplace=True)
data['locality_type'].sort_values().unique()
array(['город', 'городской посёлок', 'деревня', 'посёлок',
'посёлок при железнодорожной станции',
'садоводческое некоммерческое товарищество',
'садовое товарищество', 'село', nan], dtype=object)
Садоводческое некоммерческое товарищество (СНТ) является некоммерческой организацией, а не типом населённого пункта. Садовое товарищество правильней именовать садоводческим некоммерческим товариществом.
Садовое товарищество Приладожский — ошибочное наименование, поскольку в Ленинградской области есть садоводческое некоммерческое товарищество Приладожское, которое расположено в городском посёлке Приладожский. СНТ Рахья находится в городском посёлке Рахья. СНТ Новая Ропша находится в посёлке Ропша. Произведём соответствующие замены.
СНТ Садко и СНТ Лесная Поляна встречаются в Ленинградской области более одного раза. Поэтому записи об этих объектах удаляем.
data.loc[(data['locality_name'] == 'Приладожский') &
(data['locality_type'] == 'садовое товарищество'),
'locality_type'] = 'городской посёлок'
data.loc[(data['locality_name'] == 'Рахья') &
(data['locality_type'] == 'садовое товарищество'),
'locality_type'] = 'городской посёлок'
data.loc[(data['locality_name'] == 'Новая Ропша') &
(data['locality_type'] == 'садовое товарищество'),
['locality_name', 'locality_type']] = ['Ропша', 'посёлок']
data.drop(index=data[(data['locality_name'] == 'Садко') &
(data['locality_type'] == 'садовое товарищество')].index,
inplace=True)
data.drop(index=data[(data['locality_name'] == 'Лесная Поляна') &
(data['locality_type'] == 'садоводческое некоммерческое товарищество')].index,
inplace=True)
data['locality_type'].sort_values().unique()
array(['город', 'городской посёлок', 'деревня', 'посёлок',
'посёлок при железнодорожной станции', 'село', nan], dtype=object)
Гарболово является деревней, а не посёлком. Поэтому заменим тип населённого пункта "посёлок" на "деревня" у населённого пункта Гарболово.
data.loc[data['locality_name'] == 'Гарболово', 'locality_type'] = 'деревня'
data.loc[data['locality_name'] == 'Гарболово', 'locality_type'].unique()
array(['деревня'], dtype=object)
Кондратьево является посёлком, а не городским посёлком. Поэтому заменим тип населённого пункта.
data.loc[data['locality_name'] == 'Кондратьево', 'locality_type'] = 'посёлок'
data.loc[data['locality_name'] == 'Кондратьево', 'locality_type'].unique()
array(['посёлок'], dtype=object)
Посёлка Жил не существует. Вероятно, это посёлок Жилгородок. Произведём корректировку наименования населённого пункта.
data.loc[data['locality_name'] == 'Жил', 'locality_name'] = 'Жилгородок'
len(data.loc[data['locality_name'] == 'Жил'])
0
Посёлок Почап является деревней. Поэтому заменим тип населённого пункта.
data.loc[data['locality_name'] == 'Почап', 'locality_type'] = 'деревня'
data.loc[data['locality_name'] == 'Почап', 'locality_type'].unique()
array(['деревня'], dtype=object)
data.isna().sum().sort_values()
total_images 0 studio 0 floor 0 rooms 0 open_plan 0 total_area 0 last_price 0 first_day_exposition 0 locality_type 49 locality_name 49 floors_total 86 living_area 1903 kitchen_area 2277 days_exposition 3181 ponds_around_3000 5514 parks_around_3000 5514 city_centers_nearest 5515 airports_nearest 5538 ceiling_height 9192 balcony 11517 ponds_nearest 14585 parks_nearest 15616 is_apartment 20922 dtype: int64
locality_name теперь содержит только наименования населённых пунктов без указания на их типы. Все значения признака являются уникальными.locality_type.Описание данных признака locality_type
data['locality_type'].describe()
count 23646 unique 6 top город freq 20008 Name: locality_type, dtype: object
data['locality_type'].value_counts()
locality_type город 20008 посёлок 2090 деревня 950 городской посёлок 551 село 32 посёлок при железнодорожной станции 15 Name: count, dtype: int64
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(15, 6))
ax1.set_title('Диаграмма распределения и диаграмма размаха' +
'\nколичества уникальных значений признака locality_type')
ax1.hist(data['locality_type'].value_counts(), bins=100)
ax1.tick_params(labelbottom=False)
ax1.set_ylabel('Частота')
ax2.boxplot(data['locality_type'].value_counts(), vert=False)
ax2.tick_params(left=False, labelleft=False)
ax2.set_xlabel('Количество уникальных значений признака locality_type')
plt.show()
locality_type — тип населённого пункта
Признак является категориальным, номинальным.
Шкала измерения признака: номинальная шкала.
Значения определены для 23 646 записей — это 99,8 % всех записей.
Мода — город, её частота — 20 008.
Минимальное количество объявлений, приходящихся на один тип населённого пункта, — 15, максимальное — 20 008.
Все объекты расположены в населённых пунктах 5 типов. Наибольшее количество объектов недвижимости приходится на города. Следующий по распространённости тип населённого пункта — посёлок — на порядок реже встречается в наборе данных.
Количество значащих цифр
Особенность хранения десятичных чисел в памяти компьютера приводит к появлению после запятой лишних, незначащих цифр. Поскольку значения признака определены с точностью до 0,01 м², необходимо округлить значения до двух знаков после запятой.
data['living_area'].sort_values().unique()
array([ 2. , 3. , 5. , 5.4 , 6. ,
6.5 , 8. , 8.3 , 8.4 , 8.5 ,
8.9 , 9. , 9.1 , 9.8 , 10. ,
10.08 , 10.3 , 10.4 , 10.5 , 10.52 ,
10.55 , 10.6 , 10.7 , 10.76 , 10.8 ,
10.9 , 10.93 , 10.94 , 11. , 11.1 ,
11.15 , 11.2 , 11.3 , 11.38 , 11.4 ,
11.47 , 11.5 , 11.6 , 11.7 , 11.79 ,
11.88 , 11.9 , 11.99 , 12. , 12.08 ,
12.1 , 12.18 , 12.2 , 12.28 , 12.3 ,
12.5 , 12.6 , 12.7 , 12.71 , 12.79 ,
12.8 , 12.81 , 12.9 , 13. , 13.05 ,
13.09 , 13.1 , 13.15 , 13.2 , 13.27 ,
13.3 , 13.32 , 13.34 , 13.37 , 13.4 ,
13.46 , 13.5 , 13.54 , 13.56 , 13.59 ,
13.6 , 13.62 , 13.66 , 13.7 , 13.73 ,
13.76 , 13.79 , 13.8 , 13.82 , 13.89 ,
13.9 , 13.92 , 14. , 14.01 , 14.02 ,
14.03 , 14.06 , 14.08 , 14.1 , 14.11 ,
14.16 , 14.17 , 14.19 , 14.2 , 14.22 ,
14.23 , 14.25 , 14.28 , 14.3 , 14.31 ,
14.35 , 14.37 , 14.38 , 14.39 , 14.4 ,
14.41 , 14.45 , 14.46 , 14.47 , 14.5 ,
14.51 , 14.55 , 14.56 , 14.57 , 14.58 ,
14.59 , 14.6 , 14.62 , 14.64 , 14.65 ,
14.69 , 14.7 , 14.71 , 14.73 , 14.74 ,
14.77 , 14.8 , 14.85 , 14.89 , 14.9 ,
14.91 , 14.92 , 14.95 , 15. , 15.01 ,
15.02 , 15.03 , 15.04 , 15.05 , 15.06 ,
15.07 , 15.08 , 15.1 , 15.11 , 15.12 ,
15.13 , 15.15 , 15.16 , 15.18 , 15.2 ,
15.25 , 15.26 , 15.3 , 15.31 , 15.32 ,
15.33 , 15.34 , 15.35 , 15.36 , 15.37 ,
15.38 , 15.4 , 15.41 , 15.42 , 15.43 ,
15.45 , 15.46 , 15.5 , 15.53 , 15.54 ,
15.55 , 15.58 , 15.6 , 15.61 , 15.62 ,
15.64 , 15.65 , 15.66 , 15.7 , 15.71 ,
15.72 , 15.77 , 15.78 , 15.79 , 15.8 ,
15.82 , 15.85 , 15.86 , 15.88 , 15.89 ,
15.9 , 15.91 , 15.92 , 15.93 , 15.96 ,
16. , 16.04 , 16.06 , 16.07 , 16.08 ,
16.09 , 16.1 , 16.11 , 16.12 , 16.15 ,
16.16 , 16.18 , 16.2 , 16.22 , 16.26 ,
16.29 , 16.3 , 16.31 , 16.32 , 16.4 ,
16.41 , 16.42 , 16.47 , 16.5 , 16.51 ,
16.52 , 16.55 , 16.58 , 16.59 , 16.6 ,
16.61 , 16.62 , 16.63 , 16.66 , 16.68 ,
16.69 , 16.7 , 16.71 , 16.72 , 16.74 ,
16.76 , 16.8 , 16.83 , 16.84 , 16.88 ,
16.9 , 16.91 , 16.92 , 16.93 , 16.94 ,
16.95 , 16.96 , 16.97 , 16.98 , 17. ,
17.01 , 17.03 , 17.04 , 17.05 , 17.07 ,
17.08 , 17.1 , 17.11 , 17.12 , 17.14 ,
17.19 , 17.2 , 17.22 , 17.25 , 17.26 ,
17.27 , 17.3 , 17.33 , 17.34 , 17.35 ,
17.36 , 17.38 , 17.4 , 17.43 , 17.45 ,
17.48 , 17.49 , 17.5 , 17.5115 , 17.53 ,
17.6 , 17.62 , 17.65 , 17.66 , 17.7 ,
17.71 , 17.73 , 17.78 , 17.8 , 17.82 ,
17.83 , 17.84 , 17.85 , 17.87 , 17.9 ,
17.92 , 17.93 , 17.95 , 17.97 , 18. ,
18.02 , 18.03 , 18.04 , 18.08 , 18.09 ,
18.1 , 18.11 , 18.12 , 18.14 , 18.15 ,
18.16 , 18.19 , 18.2 , 18.23 , 18.28 ,
18.3 , 18.33 , 18.34 , 18.35 , 18.39 ,
18.4 , 18.44 , 18.46 , 18.47 , 18.5 ,
18.55 , 18.57 , 18.6 , 18.61 , 18.62 ,
18.7 , 18.72 , 18.79 , 18.8 , 18.83 ,
18.84 , 18.86 , 18.88 , 18.9 , 18.93 ,
18.95 , 19. , 19.03 , 19.1 , 19.15 ,
19.2 , 19.22 , 19.3 , 19.35 , 19.4 ,
19.5 , 19.52 , 19.55 , 19.6 , 19.65 ,
19.7 , 19.8 , 19.9 , 19.95 , 20. ,
20.02 , 20.03 , 20.1 , 20.11 , 20.13 ,
20.19 , 20.2 , 20.26 , 20.3 , 20.31 ,
20.36 , 20.39 , 20.4 , 20.46 , 20.5 ,
20.52 , 20.55 , 20.6 , 20.67 , 20.7 ,
20.74 , 20.75 , 20.77 , 20.8 , 20.9 ,
20.97 , 21. , 21.04 , 21.06 , 21.08 ,
21.09 , 21.1 , 21.11 , 21.12 , 21.15 ,
21.2 , 21.28 , 21.3 , 21.4 , 21.5 ,
21.53 , 21.59 , 21.6 , 21.65 , 21.68 ,
21.7 , 21.77 , 21.8 , 21.9 , 22. ,
22.04 , 22.1 , 22.15 , 22.2 , 22.3 ,
22.35 , 22.37 , 22.4 , 22.43 , 22.45 ,
22.5 , 22.57 , 22.6 , 22.62 , 22.7 ,
22.8 , 22.81 , 22.9 , 23. , 23.1 ,
23.19 , 23.2 , 23.3 , 23.4 , 23.43 ,
23.5 , 23.6 , 23.7 , 23.77 , 23.8 ,
23.9 , 24. , 24.1 , 24.2 , 24.3 ,
24.4 , 24.42 , 24.5 , 24.6 , 24.64 ,
24.7 , 24.75 , 24.77 , 24.8 , 24.83 ,
24.86 , 24.89 , 24.9 , 25. , 25.1 ,
25.2 , 25.3 , 25.38 , 25.4 , 25.41 ,
25.44 , 25.5 , 25.6 , 25.7 , 25.8 ,
25.81 , 25.9 , 25.900002, 25.95 , 25.97 ,
26. , 26.1 , 26.13 , 26.2 , 26.21 ,
26.28 , 26.29 , 26.3 , 26.4 , 26.5 ,
26.51 , 26.599998, 26.6 , 26.61 , 26.7 ,
26.75 , 26.79 , 26.8 , 26.87 , 26.9 ,
26.94 , 27. , 27.05 , 27.06 , 27.1 ,
27.12 , 27.2 , 27.22 , 27.25 , 27.29 ,
27.3 , 27.33 , 27.380001, 27.4 , 27.42 ,
27.43 , 27.46 , 27.5 , 27.51 , 27.57 ,
27.6 , 27.67 , 27.69 , 27.7 , 27.75 ,
27.77 , 27.8 , 27.88 , 27.89 , 27.9 ,
27.92 , 27.95 , 28. , 28.01 , 28.02 ,
28.07 , 28.09 , 28.1 , 28.14 , 28.15 ,
28.18 , 28.2 , 28.23 , 28.26 , 28.3 ,
28.300001, 28.31 , 28.33 , 28.34 , 28.36 ,
28.4 , 28.42 , 28.43 , 28.45 , 28.47 ,
28.48 , 28.5 , 28.54 , 28.55 , 28.6 ,
28.66 , 28.7 , 28.71 , 28.73 , 28.77 ,
28.8 , 28.81 , 28.84 , 28.85 , 28.86 ,
28.88 , 28.9 , 28.900002, 28.98 , 29. ,
29.01 , 29.08 , 29.1 , 29.13 , 29.16 ,
29.2 , 29.21 , 29.22 , 29.27 , 29.3 ,
29.34 , 29.38 , 29.4 , 29.41 , 29.43 ,
29.48 , 29.5 , 29.52 , 29.55 , 29.56 ,
29.599998, 29.6 , 29.61 , 29.67 , 29.7 ,
29.72 , 29.74 , 29.77 , 29.78 , 29.8 ,
29.81 , 29.83 , 29.84 , 29.85 , 29.9 ,
29.92 , 30. , 30.01 , 30.04 , 30.05 ,
30.08 , 30.099998, 30.1 , 30.12 , 30.15 ,
30.16 , 30.17 , 30.2 , 30.29 , 30.3 ,
30.31 , 30.35 , 30.39 , 30.4 , 30.5 ,
30.52 , 30.55 , 30.57 , 30.59 , 30.6 ,
30.61 , 30.62 , 30.7 , 30.72 , 30.75 ,
30.8 , 30.81 , 30.82 , 30.83 , 30.89 ,
30.9 , 30.900002, 30.92 , 31. , 31.01 ,
31.04 , 31.05 , 31.07 , 31.1 , 31.12 ,
31.18 , 31.2 , 31.26 , 31.29 , 31.3 ,
31.38 , 31.4 , 31.41 , 31.42 , 31.43 ,
31.44 , 31.47 , 31.48 , 31.5 , 31.51 ,
31.52 , 31.55 , 31.599998, 31.6 , 31.61 ,
31.62 , 31.64 , 31.65 , 31.7 , 31.71 ,
31.74 , 31.77 , 31.8 , 31.81 , 31.9 ,
32. , 32.02 , 32.04 , 32.05 , 32.06 ,
32.08 , 32.1 , 32.199997, 32.2 , 32.26 ,
32.3 , 32.35 , 32.37 , 32.38 , 32.4 ,
32.46 , 32.5 , 32.6 , 32.61 , 32.62 ,
32.7 , 32.71 , 32.73 , 32.79 , 32.8 ,
32.84 , 32.9 , 32.95 , 33. , 33.03 ,
33.06 , 33.08 , 33.1 , 33.18 , 33.2 ,
33.26 , 33.260002, 33.3 , 33.36 , 33.4 ,
33.47 , 33.5 , 33.57 , 33.6 , 33.63 ,
33.67 , 33.7 , 33.72 , 33.73 , 33.8 ,
33.87 , 33.9 , 33.92 , 34. , 34.1 ,
34.14 , 34.2 , 34.29 , 34.3 , 34.32 ,
34.37 , 34.4 , 34.41 , 34.44 , 34.5 ,
34.51 , 34.6 , 34.63 , 34.7 , 34.760002,
34.79 , 34.8 , 34.87 , 34.88 , 34.9 ,
35. , 35.01 , 35.05 , 35.07 , 35.1 ,
35.17 , 35.2 , 35.3 , 35.33 , 35.38 ,
35.4 , 35.48 , 35.5 , 35.55 , 35.6 ,
35.61 , 35.7 , 35.74 , 35.76 , 35.77 ,
35.8 , 35.81 , 35.88 , 35.89 , 35.9 ,
35.91 , 35.92 , 36. , 36.04 , 36.07 ,
36.1 , 36.15 , 36.2 , 36.27 , 36.3 ,
36.35 , 36.4 , 36.45 , 36.5 , 36.57 ,
36.6 , 36.7 , 36.76 , 36.79 , 36.8 ,
36.81 , 36.86 , 36.9 , 36.95 , 37. ,
37.1 , 37.13 , 37.2 , 37.28 , 37.3 ,
37.300003, 37.4 , 37.5 , 37.52 , 37.6 ,
37.66 , 37.7 , 37.74 , 37.8 , 37.9 ,
38. , 38.03 , 38.05 , 38.07 , 38.1 ,
38.18 , 38.2 , 38.3 , 38.33 , 38.39 ,
38.4 , 38.5 , 38.6 , 38.7 , 38.73 ,
38.8 , 38.9 , 38.91 , 38.95 , 38.99 ,
39. , 39.07 , 39.1 , 39.18 , 39.2 ,
39.3 , 39.4 , 39.41 , 39.5 , 39.59 ,
39.6 , 39.62 , 39.66 , 39.7 , 39.71 ,
39.78 , 39.8 , 39.85 , 39.9 , 40. ,
40.06 , 40.1 , 40.2 , 40.3 , 40.32 ,
40.39 , 40.4 , 40.43 , 40.5 , 40.57 ,
40.59 , 40.6 , 40.61 , 40.7 , 40.79 ,
40.8 , 40.83 , 40.9 , 40.92 , 40.95 ,
41. , 41.05 , 41.06 , 41.08 , 41.1 ,
41.17 , 41.19 , 41.2 , 41.3 , 41.34 ,
41.35 , 41.4 , 41.44 , 41.5 , 41.6 ,
41.69 , 41.7 , 41.8 , 41.9 , 41.92 ,
41.98 , 42. , 42.1 , 42.17 , 42.2 ,
42.26 , 42.3 , 42.31 , 42.4 , 42.41 ,
42.43 , 42.48 , 42.5 , 42.54 , 42.55 ,
42.6 , 42.7 , 42.8 , 42.9 , 42.91 ,
43. , 43.05 , 43.1 , 43.15 , 43.2 ,
43.3 , 43.32 , 43.4 , 43.45 , 43.46 ,
43.5 , 43.6 , 43.62 , 43.63 , 43.7 ,
43.71 , 43.78 , 43.8 , 43.81 , 43.83 ,
43.89 , 43.9 , 43.92 , 44. , 44.000004,
44.04 , 44.05 , 44.1 , 44.100002, 44.13 ,
44.15 , 44.2 , 44.3 , 44.4 , 44.5 ,
44.56 , 44.6 , 44.7 , 44.8 , 44.9 ,
44.91 , 44.99 , 45. , 45.1 , 45.11 ,
45.13 , 45.18 , 45.2 , 45.23 , 45.3 ,
45.34 , 45.38 , 45.4 , 45.5 , 45.6 ,
45.7 , 45.72 , 45.8 , 45.82 , 45.85 ,
45.86 , 45.9 , 45.92 , 45.95 , 46. ,
46.01 , 46.05 , 46.1 , 46.13 , 46.14 ,
46.15 , 46.2 , 46.3 , 46.4 , 46.5 ,
46.57 , 46.6 , 46.64 , 46.7 , 46.75 ,
46.8 , 46.9 , 47. , 47.1 , 47.11 ,
47.2 , 47.24 , 47.3 , 47.37 , 47.4 ,
47.43 , 47.5 , 47.53 , 47.6 , 47.68 ,
47.7 , 47.8 , 47.9 , 47.999996, 48. ,
48.05 , 48.1 , 48.13 , 48.2 , 48.25 ,
48.3 , 48.300003, 48.35 , 48.36 , 48.38 ,
48.4 , 48.41 , 48.42 , 48.45 , 48.46 ,
48.48 , 48.49 , 48.5 , 48.6 , 48.62 ,
48.7 , 48.8 , 48.84 , 48.88 , 48.9 ,
48.93 , 48.94 , 49. , 49.1 , 49.2 ,
49.25 , 49.27 , 49.28 , 49.3 , 49.33 ,
49.4 , 49.46 , 49.5 , 49.58 , 49.6 ,
49.7 , 49.74 , 49.8 , 49.87 , 49.9 ,
49.98 , 50. , 50.02 , 50.08 , 50.1 ,
50.16 , 50.2 , 50.25 , 50.26 , 50.28 ,
50.3 , 50.34 , 50.4 , 50.47 , 50.5 ,
50.6 , 50.64 , 50.7 , 50.8 , 50.81 ,
50.9 , 51. , 51.07 , 51.1 , 51.2 ,
51.3 , 51.4 , 51.5 , 51.6 , 51.7 ,
51.76 , 51.78 , 51.8 , 51.88 , 51.9 ,
52. , 52.02 , 52.1 , 52.2 , 52.21 ,
52.26 , 52.3 , 52.4 , 52.5 , 52.53 ,
52.6 , 52.65 , 52.7 , 52.77 , 52.8 ,
52.9 , 52.94 , 53. , 53.1 , 53.15 ,
53.17 , 53.2 , 53.3 , 53.31 , 53.33 ,
53.35 , 53.4 , 53.5 , 53.6 , 53.7 ,
53.8 , 53.9 , 54. , 54.09 , 54.1 ,
54.13 , 54.2 , 54.3 , 54.4 , 54.43 ,
54.48 , 54.5 , 54.6 , 54.7 , 54.74 ,
54.8 , 54.9 , 55. , 55.1 , 55.2 ,
55.22 , 55.3 , 55.35 , 55.38 , 55.4 ,
55.5 , 55.6 , 55.7 , 55.8 , 55.84 ,
55.9 , 56. , 56.1 , 56.12 , 56.2 ,
56.3 , 56.4 , 56.5 , 56.53 , 56.6 ,
56.7 , 56.8 , 56.86 , 56.9 , 57. ,
57.1 , 57.2 , 57.3 , 57.35 , 57.4 ,
57.5 , 57.51 , 57.6 , 57.7 , 57.75 ,
57.8 , 57.9 , 58. , 58.1 , 58.18 ,
58.2 , 58.3 , 58.4 , 58.44 , 58.5 ,
58.6 , 58.63 , 58.7 , 58.8 , 58.82 ,
59. , 59.1 , 59.12 , 59.2 , 59.3 ,
59.4 , 59.5 , 59.6 , 59.7 , 59.8 ,
59.9 , 60. , 60.1 , 60.2 , 60.3 ,
60.300003, 60.33 , 60.4 , 60.5 , 60.6 ,
60.7 , 60.77 , 60.8 , 60.9 , 61. ,
61.1 , 61.2 , 61.3 , 61.35 , 61.4 ,
61.5 , 61.6 , 61.7 , 61.8 , 61.9 ,
62. , 62.1 , 62.2 , 62.3 , 62.4 ,
62.5 , 62.6 , 62.7 , 62.75 , 62.8 ,
62.9 , 63. , 63.1 , 63.2 , 63.3 ,
63.31 , 63.4 , 63.5 , 63.6 , 63.7 ,
63.72 , 63.8 , 63.9 , 64. , 64.1 ,
64.2 , 64.3 , 64.32 , 64.4 , 64.5 ,
64.6 , 64.7 , 64.8 , 64.9 , 65. ,
65.3 , 65.4 , 65.5 , 65.6 , 65.7 ,
65.72 , 65.8 , 65.9 , 65.93 , 66. ,
66.01 , 66.1 , 66.2 , 66.22 , 66.24 ,
66.3 , 66.4 , 66.5 , 66.6 , 66.7 ,
66.8 , 66.9 , 66.99 , 67. , 67.01 ,
67.1 , 67.2 , 67.3 , 67.4 , 67.5 ,
67.6 , 67.8 , 67.81 , 67.9 , 68. ,
68.1 , 68.3 , 68.4 , 68.48 , 68.5 ,
68.6 , 68.7 , 68.8 , 68.9 , 69. ,
69.1 , 69.2 , 69.28 , 69.3 , 69.5 ,
69.6 , 69.7 , 69.75 , 69.8 , 69.9 ,
70. , 70.1 , 70.3 , 70.4 , 70.48 ,
70.5 , 70.6 , 70.7 , 70.9 , 71. ,
71.1 , 71.2 , 71.3 , 71.4 , 71.5 ,
71.7 , 71.72 , 71.9 , 72. , 72.1 ,
72.2 , 72.3 , 72.4 , 72.5 , 72.52 ,
72.6 , 72.7 , 72.79 , 72.8 , 73. ,
73.1 , 73.2 , 73.3 , 73.4 , 73.5 ,
73.6 , 73.8 , 73.9 , 74. , 74.1 ,
74.16 , 74.2 , 74.3 , 74.4 , 74.6 ,
74.8 , 74.99 , 75. , 75.1 , 75.2 ,
75.25 , 75.4 , 75.5 , 75.6 , 75.7 ,
75.8 , 75.83 , 76. , 76.1 , 76.2 ,
76.3 , 76.4 , 76.5 , 76.65 , 76.7 ,
76.8 , 76.9 , 77. , 77.1 , 77.2 ,
77.3 , 77.35 , 77.4 , 77.5 , 77.6 ,
77.61 , 77.71 , 77.8 , 78. , 78.03 ,
78.4 , 78.5 , 78.6 , 78.9 , 79. ,
79.2 , 79.28 , 79.3 , 79.34 , 79.4 ,
79.42 , 79.5 , 79.7 , 79.74 , 80. ,
80.1 , 80.2 , 80.3 , 80.39 , 80.5 ,
80.62 , 80.7 , 80.8 , 80.9 , 81. ,
81.1 , 81.3 , 81.4 , 81.5 , 81.6 ,
81.66 , 81.7 , 81.899994, 81.9 , 82. ,
82.05 , 82.1 , 82.2 , 82.3 , 82.4 ,
82.55 , 82.8 , 82.9 , 83. , 83.2 ,
83.5 , 83.6 , 83.7 , 83.8 , 84. ,
84.1 , 84.2 , 84.5 , 84.6 , 84.69 ,
84.7 , 85. , 85.1 , 85.2 , 85.3 ,
85.6 , 86. , 86.1 , 86.2 , 86.6 ,
86.7 , 87. , 87.2 , 87.23 , 87.5 ,
87.7 , 87.8 , 88. , 88.1 , 88.2 ,
88.3 , 89. , 89.100006, 89.11 , 89.2 ,
89.3 , 89.4 , 89.5 , 89.6 , 89.7 ,
89.9 , 90. , 90.2 , 90.6 , 90.7 ,
91. , 91.2 , 91.24 , 91.7 , 91.77 ,
91.8 , 92. , 92.1 , 92.3 , 92.34 ,
92.5 , 92.6 , 92.7 , 92.8 , 92.9 ,
93. , 93.1 , 93.2 , 93.5 , 93.6 ,
94. , 94.1 , 94.4 , 94.54 , 94.8 ,
94.89 , 94.9 , 95. , 95.1 , 95.2 ,
95.4 , 95.41 , 95.45 , 95.6 , 95.7 ,
95.9 , 96. , 96.3 , 96.4 , 96.6 ,
96.7 , 97. , 97.2 , 97.3 , 97.6 ,
98. , 98.2 , 98.5 , 98.7 , 98.9 ,
99. , 99.1 , 99.21 , 99.3 , 99.5 ,
99.6 , 99.7 , 99.8 , 99.9 , 100. ,
100.1 , 100.23 , 100.4 , 100.7 , 100.9 ,
101. , 101.2 , 101.54 , 101.82 , 102. ,
102.2 , 102.3 , 102.5 , 102.8 , 103. ,
103.1 , 103.3 , 103.6 , 103.7 , 103.8 ,
104. , 104.1 , 104.2 , 104.76 , 104.8 ,
105. , 105.3 , 105.8 , 106. , 106.1 ,
106.2 , 106.4 , 106.5 , 107. , 107.03 ,
107.6 , 108. , 108.8 , 109. , 109.4 ,
109.51 , 110. , 110.3 , 110.4 , 110.8 ,
111. , 111.1 , 111.6 , 111.86 , 112. ,
112.2 , 112.4 , 112.7 , 113. , 114. ,
114.7 , 114.8 , 115. , 115.5 , 115.8 ,
116. , 116.2 , 117. , 117.1 , 117.3 ,
117.4 , 118.4 , 118.5 , 118.9 , 119. ,
119.3 , 119.5 , 119.9 , 120. , 121. ,
121.6 , 122. , 122.1 , 123. , 123.1 ,
123.27 , 123.6 , 123.9 , 124. , 124.9 ,
125. , 125.1 , 125.5 , 125.7 , 125.9 ,
126. , 126.4 , 126.6 , 127. , 127.7 ,
128. , 129. , 130. , 130.3 , 131. ,
131.5 , 132. , 133. , 133.4 , 134. ,
134.7 , 134.8 , 136. , 136.1 , 136.2 ,
137.7 , 138.8 , 139. , 139.4 , 139.8 ,
140. , 141. , 142. , 143. , 144.5 ,
144.6 , 145. , 145.4 , 145.5 , 145.9 ,
147. , 147.2 , 148. , 148.6 , 149.4 ,
150. , 150.4 , 150.8 , 151. , 151.1 ,
151.4 , 151.6 , 152. , 153. , 153.9 ,
154. , 154.7 , 155. , 155.1 , 155.5 ,
157. , 159.2 , 159.5 , 159.6 , 159.9 ,
160. , 160.1 , 160.6 , 161.4 , 162. ,
163.2 , 163.5 , 164.3 , 164.7 , 165. ,
165.5 , 166.7 , 167. , 168.3 , 170. ,
170.8 , 171. , 174. , 174.3 , 175. ,
176.2 , 176.6 , 177. , 177.3 , 179. ,
179.2 , 180. , 181.8 , 182. , 182.8 ,
183. , 183.7 , 184. , 184.9 , 187. ,
187.9 , 188.7 , 189.4 , 190. , 193. ,
193.5 , 194. , 195. , 198. , 199. ,
200. , 204. , 211. , 216. , 218. ,
220. , 222. , 225.9 , 230. , 239.4 ,
248.5 , 248.7 , 250. , 255.7 , 258. ,
260. , 264.5 , 274. , 279.6 , 300. ,
301.5 , 312.5 , 322.3 , 332. , 347.5 ,
409. , 409.7 , nan])
data['living_area'] = data[data['living_area'].notna()]['living_area'].round(2)
data['living_area'].sort_values().unique()
array([ 2. , 3. , 5. , 5.4 , 6. , 6.5 , 8. , 8.3 ,
8.4 , 8.5 , 8.9 , 9. , 9.1 , 9.8 , 10. , 10.08,
10.3 , 10.4 , 10.5 , 10.52, 10.55, 10.6 , 10.7 , 10.76,
10.8 , 10.9 , 10.93, 10.94, 11. , 11.1 , 11.15, 11.2 ,
11.3 , 11.38, 11.4 , 11.47, 11.5 , 11.6 , 11.7 , 11.79,
11.88, 11.9 , 11.99, 12. , 12.08, 12.1 , 12.18, 12.2 ,
12.28, 12.3 , 12.5 , 12.6 , 12.7 , 12.71, 12.79, 12.8 ,
12.81, 12.9 , 13. , 13.05, 13.09, 13.1 , 13.15, 13.2 ,
13.27, 13.3 , 13.32, 13.34, 13.37, 13.4 , 13.46, 13.5 ,
13.54, 13.56, 13.59, 13.6 , 13.62, 13.66, 13.7 , 13.73,
13.76, 13.79, 13.8 , 13.82, 13.89, 13.9 , 13.92, 14. ,
14.01, 14.02, 14.03, 14.06, 14.08, 14.1 , 14.11, 14.16,
14.17, 14.19, 14.2 , 14.22, 14.23, 14.25, 14.28, 14.3 ,
14.31, 14.35, 14.37, 14.38, 14.39, 14.4 , 14.41, 14.45,
14.46, 14.47, 14.5 , 14.51, 14.55, 14.56, 14.57, 14.58,
14.59, 14.6 , 14.62, 14.64, 14.65, 14.69, 14.7 , 14.71,
14.73, 14.74, 14.77, 14.8 , 14.85, 14.89, 14.9 , 14.91,
14.92, 14.95, 15. , 15.01, 15.02, 15.03, 15.04, 15.05,
15.06, 15.07, 15.08, 15.1 , 15.11, 15.12, 15.13, 15.15,
15.16, 15.18, 15.2 , 15.25, 15.26, 15.3 , 15.31, 15.32,
15.33, 15.34, 15.35, 15.36, 15.37, 15.38, 15.4 , 15.41,
15.42, 15.43, 15.45, 15.46, 15.5 , 15.53, 15.54, 15.55,
15.58, 15.6 , 15.61, 15.62, 15.64, 15.65, 15.66, 15.7 ,
15.71, 15.72, 15.77, 15.78, 15.79, 15.8 , 15.82, 15.85,
15.86, 15.88, 15.89, 15.9 , 15.91, 15.92, 15.93, 15.96,
16. , 16.04, 16.06, 16.07, 16.08, 16.09, 16.1 , 16.11,
16.12, 16.15, 16.16, 16.18, 16.2 , 16.22, 16.26, 16.29,
16.3 , 16.31, 16.32, 16.4 , 16.41, 16.42, 16.47, 16.5 ,
16.51, 16.52, 16.55, 16.58, 16.59, 16.6 , 16.61, 16.62,
16.63, 16.66, 16.68, 16.69, 16.7 , 16.71, 16.72, 16.74,
16.76, 16.8 , 16.83, 16.84, 16.88, 16.9 , 16.91, 16.92,
16.93, 16.94, 16.95, 16.96, 16.97, 16.98, 17. , 17.01,
17.03, 17.04, 17.05, 17.07, 17.08, 17.1 , 17.11, 17.12,
17.14, 17.19, 17.2 , 17.22, 17.25, 17.26, 17.27, 17.3 ,
17.33, 17.34, 17.35, 17.36, 17.38, 17.4 , 17.43, 17.45,
17.48, 17.49, 17.5 , 17.51, 17.53, 17.6 , 17.62, 17.65,
17.66, 17.7 , 17.71, 17.73, 17.78, 17.8 , 17.82, 17.83,
17.84, 17.85, 17.87, 17.9 , 17.92, 17.93, 17.95, 17.97,
18. , 18.02, 18.03, 18.04, 18.08, 18.09, 18.1 , 18.11,
18.12, 18.14, 18.15, 18.16, 18.19, 18.2 , 18.23, 18.28,
18.3 , 18.33, 18.34, 18.35, 18.39, 18.4 , 18.44, 18.46,
18.47, 18.5 , 18.55, 18.57, 18.6 , 18.61, 18.62, 18.7 ,
18.72, 18.79, 18.8 , 18.83, 18.84, 18.86, 18.88, 18.9 ,
18.93, 18.95, 19. , 19.03, 19.1 , 19.15, 19.2 , 19.22,
19.3 , 19.35, 19.4 , 19.5 , 19.52, 19.55, 19.6 , 19.65,
19.7 , 19.8 , 19.9 , 19.95, 20. , 20.02, 20.03, 20.1 ,
20.11, 20.13, 20.19, 20.2 , 20.26, 20.3 , 20.31, 20.36,
20.39, 20.4 , 20.46, 20.5 , 20.52, 20.55, 20.6 , 20.67,
20.7 , 20.74, 20.75, 20.77, 20.8 , 20.9 , 20.97, 21. ,
21.04, 21.06, 21.08, 21.09, 21.1 , 21.11, 21.12, 21.15,
21.2 , 21.28, 21.3 , 21.4 , 21.5 , 21.53, 21.59, 21.6 ,
21.65, 21.68, 21.7 , 21.77, 21.8 , 21.9 , 22. , 22.04,
22.1 , 22.15, 22.2 , 22.3 , 22.35, 22.37, 22.4 , 22.43,
22.45, 22.5 , 22.57, 22.6 , 22.62, 22.7 , 22.8 , 22.81,
22.9 , 23. , 23.1 , 23.19, 23.2 , 23.3 , 23.4 , 23.43,
23.5 , 23.6 , 23.7 , 23.77, 23.8 , 23.9 , 24. , 24.1 ,
24.2 , 24.3 , 24.4 , 24.42, 24.5 , 24.6 , 24.64, 24.7 ,
24.75, 24.77, 24.8 , 24.83, 24.86, 24.89, 24.9 , 25. ,
25.1 , 25.2 , 25.3 , 25.38, 25.4 , 25.41, 25.44, 25.5 ,
25.6 , 25.7 , 25.8 , 25.81, 25.9 , 25.95, 25.97, 26. ,
26.1 , 26.13, 26.2 , 26.21, 26.28, 26.29, 26.3 , 26.4 ,
26.5 , 26.51, 26.6 , 26.61, 26.7 , 26.75, 26.79, 26.8 ,
26.87, 26.9 , 26.94, 27. , 27.05, 27.06, 27.1 , 27.12,
27.2 , 27.22, 27.25, 27.29, 27.3 , 27.33, 27.38, 27.4 ,
27.42, 27.43, 27.46, 27.5 , 27.51, 27.57, 27.6 , 27.67,
27.69, 27.7 , 27.75, 27.77, 27.8 , 27.88, 27.89, 27.9 ,
27.92, 27.95, 28. , 28.01, 28.02, 28.07, 28.09, 28.1 ,
28.14, 28.15, 28.18, 28.2 , 28.23, 28.26, 28.3 , 28.31,
28.33, 28.34, 28.36, 28.4 , 28.42, 28.43, 28.45, 28.47,
28.48, 28.5 , 28.54, 28.55, 28.6 , 28.66, 28.7 , 28.71,
28.73, 28.77, 28.8 , 28.81, 28.84, 28.85, 28.86, 28.88,
28.9 , 28.98, 29. , 29.01, 29.08, 29.1 , 29.13, 29.16,
29.2 , 29.21, 29.22, 29.27, 29.3 , 29.34, 29.38, 29.4 ,
29.41, 29.43, 29.48, 29.5 , 29.52, 29.55, 29.56, 29.6 ,
29.61, 29.67, 29.7 , 29.72, 29.74, 29.77, 29.78, 29.8 ,
29.81, 29.83, 29.84, 29.85, 29.9 , 29.92, 30. , 30.01,
30.04, 30.05, 30.08, 30.1 , 30.12, 30.15, 30.16, 30.17,
30.2 , 30.29, 30.3 , 30.31, 30.35, 30.39, 30.4 , 30.5 ,
30.52, 30.55, 30.57, 30.59, 30.6 , 30.61, 30.62, 30.7 ,
30.72, 30.75, 30.8 , 30.81, 30.82, 30.83, 30.89, 30.9 ,
30.92, 31. , 31.01, 31.04, 31.05, 31.07, 31.1 , 31.12,
31.18, 31.2 , 31.26, 31.29, 31.3 , 31.38, 31.4 , 31.41,
31.42, 31.43, 31.44, 31.47, 31.48, 31.5 , 31.51, 31.52,
31.55, 31.6 , 31.61, 31.62, 31.64, 31.65, 31.7 , 31.71,
31.74, 31.77, 31.8 , 31.81, 31.9 , 32. , 32.02, 32.04,
32.05, 32.06, 32.08, 32.1 , 32.2 , 32.26, 32.3 , 32.35,
32.37, 32.38, 32.4 , 32.46, 32.5 , 32.6 , 32.61, 32.62,
32.7 , 32.71, 32.73, 32.79, 32.8 , 32.84, 32.9 , 32.95,
33. , 33.03, 33.06, 33.08, 33.1 , 33.18, 33.2 , 33.26,
33.3 , 33.36, 33.4 , 33.47, 33.5 , 33.57, 33.6 , 33.63,
33.67, 33.7 , 33.72, 33.73, 33.8 , 33.87, 33.9 , 33.92,
34. , 34.1 , 34.14, 34.2 , 34.29, 34.3 , 34.32, 34.37,
34.4 , 34.41, 34.44, 34.5 , 34.51, 34.6 , 34.63, 34.7 ,
34.76, 34.79, 34.8 , 34.87, 34.88, 34.9 , 35. , 35.01,
35.05, 35.07, 35.1 , 35.17, 35.2 , 35.3 , 35.33, 35.38,
35.4 , 35.48, 35.5 , 35.55, 35.6 , 35.61, 35.7 , 35.74,
35.76, 35.77, 35.8 , 35.81, 35.88, 35.89, 35.9 , 35.91,
35.92, 36. , 36.04, 36.07, 36.1 , 36.15, 36.2 , 36.27,
36.3 , 36.35, 36.4 , 36.45, 36.5 , 36.57, 36.6 , 36.7 ,
36.76, 36.79, 36.8 , 36.81, 36.86, 36.9 , 36.95, 37. ,
37.1 , 37.13, 37.2 , 37.28, 37.3 , 37.4 , 37.5 , 37.52,
37.6 , 37.66, 37.7 , 37.74, 37.8 , 37.9 , 38. , 38.03,
38.05, 38.07, 38.1 , 38.18, 38.2 , 38.3 , 38.33, 38.39,
38.4 , 38.5 , 38.6 , 38.7 , 38.73, 38.8 , 38.9 , 38.91,
38.95, 38.99, 39. , 39.07, 39.1 , 39.18, 39.2 , 39.3 ,
39.4 , 39.41, 39.5 , 39.59, 39.6 , 39.62, 39.66, 39.7 ,
39.71, 39.78, 39.8 , 39.85, 39.9 , 40. , 40.06, 40.1 ,
40.2 , 40.3 , 40.32, 40.39, 40.4 , 40.43, 40.5 , 40.57,
40.59, 40.6 , 40.61, 40.7 , 40.79, 40.8 , 40.83, 40.9 ,
40.92, 40.95, 41. , 41.05, 41.06, 41.08, 41.1 , 41.17,
41.19, 41.2 , 41.3 , 41.34, 41.35, 41.4 , 41.44, 41.5 ,
41.6 , 41.69, 41.7 , 41.8 , 41.9 , 41.92, 41.98, 42. ,
42.1 , 42.17, 42.2 , 42.26, 42.3 , 42.31, 42.4 , 42.41,
42.43, 42.48, 42.5 , 42.54, 42.55, 42.6 , 42.7 , 42.8 ,
42.9 , 42.91, 43. , 43.05, 43.1 , 43.15, 43.2 , 43.3 ,
43.32, 43.4 , 43.45, 43.46, 43.5 , 43.6 , 43.62, 43.63,
43.7 , 43.71, 43.78, 43.8 , 43.81, 43.83, 43.89, 43.9 ,
43.92, 44. , 44.04, 44.05, 44.1 , 44.13, 44.15, 44.2 ,
44.3 , 44.4 , 44.5 , 44.56, 44.6 , 44.7 , 44.8 , 44.9 ,
44.91, 44.99, 45. , 45.1 , 45.11, 45.13, 45.18, 45.2 ,
45.23, 45.3 , 45.34, 45.38, 45.4 , 45.5 , 45.6 , 45.7 ,
45.72, 45.8 , 45.82, 45.85, 45.86, 45.9 , 45.92, 45.95,
46. , 46.01, 46.05, 46.1 , 46.13, 46.14, 46.15, 46.2 ,
46.3 , 46.4 , 46.5 , 46.57, 46.6 , 46.64, 46.7 , 46.75,
46.8 , 46.9 , 47. , 47.1 , 47.11, 47.2 , 47.24, 47.3 ,
47.37, 47.4 , 47.43, 47.5 , 47.53, 47.6 , 47.68, 47.7 ,
47.8 , 47.9 , 48. , 48.05, 48.1 , 48.13, 48.2 , 48.25,
48.3 , 48.35, 48.36, 48.38, 48.4 , 48.41, 48.42, 48.45,
48.46, 48.48, 48.49, 48.5 , 48.6 , 48.62, 48.7 , 48.8 ,
48.84, 48.88, 48.9 , 48.93, 48.94, 49. , 49.1 , 49.2 ,
49.25, 49.27, 49.28, 49.3 , 49.33, 49.4 , 49.46, 49.5 ,
49.58, 49.6 , 49.7 , 49.74, 49.8 , 49.87, 49.9 , 49.98,
50. , 50.02, 50.08, 50.1 , 50.16, 50.2 , 50.25, 50.26,
50.28, 50.3 , 50.34, 50.4 , 50.47, 50.5 , 50.6 , 50.64,
50.7 , 50.8 , 50.81, 50.9 , 51. , 51.07, 51.1 , 51.2 ,
51.3 , 51.4 , 51.5 , 51.6 , 51.7 , 51.76, 51.78, 51.8 ,
51.88, 51.9 , 52. , 52.02, 52.1 , 52.2 , 52.21, 52.26,
52.3 , 52.4 , 52.5 , 52.53, 52.6 , 52.65, 52.7 , 52.77,
52.8 , 52.9 , 52.94, 53. , 53.1 , 53.15, 53.17, 53.2 ,
53.3 , 53.31, 53.33, 53.35, 53.4 , 53.5 , 53.6 , 53.7 ,
53.8 , 53.9 , 54. , 54.09, 54.1 , 54.13, 54.2 , 54.3 ,
54.4 , 54.43, 54.48, 54.5 , 54.6 , 54.7 , 54.74, 54.8 ,
54.9 , 55. , 55.1 , 55.2 , 55.22, 55.3 , 55.35, 55.38,
55.4 , 55.5 , 55.6 , 55.7 , 55.8 , 55.84, 55.9 , 56. ,
56.1 , 56.12, 56.2 , 56.3 , 56.4 , 56.5 , 56.53, 56.6 ,
56.7 , 56.8 , 56.86, 56.9 , 57. , 57.1 , 57.2 , 57.3 ,
57.35, 57.4 , 57.5 , 57.51, 57.6 , 57.7 , 57.75, 57.8 ,
57.9 , 58. , 58.1 , 58.18, 58.2 , 58.3 , 58.4 , 58.44,
58.5 , 58.6 , 58.63, 58.7 , 58.8 , 58.82, 59. , 59.1 ,
59.12, 59.2 , 59.3 , 59.4 , 59.5 , 59.6 , 59.7 , 59.8 ,
59.9 , 60. , 60.1 , 60.2 , 60.3 , 60.33, 60.4 , 60.5 ,
60.6 , 60.7 , 60.77, 60.8 , 60.9 , 61. , 61.1 , 61.2 ,
61.3 , 61.35, 61.4 , 61.5 , 61.6 , 61.7 , 61.8 , 61.9 ,
62. , 62.1 , 62.2 , 62.3 , 62.4 , 62.5 , 62.6 , 62.7 ,
62.75, 62.8 , 62.9 , 63. , 63.1 , 63.2 , 63.3 , 63.31,
63.4 , 63.5 , 63.6 , 63.7 , 63.72, 63.8 , 63.9 , 64. ,
64.1 , 64.2 , 64.3 , 64.32, 64.4 , 64.5 , 64.6 , 64.7 ,
64.8 , 64.9 , 65. , 65.3 , 65.4 , 65.5 , 65.6 , 65.7 ,
65.72, 65.8 , 65.9 , 65.93, 66. , 66.01, 66.1 , 66.2 ,
66.22, 66.24, 66.3 , 66.4 , 66.5 , 66.6 , 66.7 , 66.8 ,
66.9 , 66.99, 67. , 67.01, 67.1 , 67.2 , 67.3 , 67.4 ,
67.5 , 67.6 , 67.8 , 67.81, 67.9 , 68. , 68.1 , 68.3 ,
68.4 , 68.48, 68.5 , 68.6 , 68.7 , 68.8 , 68.9 , 69. ,
69.1 , 69.2 , 69.28, 69.3 , 69.5 , 69.6 , 69.7 , 69.75,
69.8 , 69.9 , 70. , 70.1 , 70.3 , 70.4 , 70.48, 70.5 ,
70.6 , 70.7 , 70.9 , 71. , 71.1 , 71.2 , 71.3 , 71.4 ,
71.5 , 71.7 , 71.72, 71.9 , 72. , 72.1 , 72.2 , 72.3 ,
72.4 , 72.5 , 72.52, 72.6 , 72.7 , 72.79, 72.8 , 73. ,
73.1 , 73.2 , 73.3 , 73.4 , 73.5 , 73.6 , 73.8 , 73.9 ,
74. , 74.1 , 74.16, 74.2 , 74.3 , 74.4 , 74.6 , 74.8 ,
74.99, 75. , 75.1 , 75.2 , 75.25, 75.4 , 75.5 , 75.6 ,
75.7 , 75.8 , 75.83, 76. , 76.1 , 76.2 , 76.3 , 76.4 ,
76.5 , 76.65, 76.7 , 76.8 , 76.9 , 77. , 77.1 , 77.2 ,
77.3 , 77.35, 77.4 , 77.5 , 77.6 , 77.61, 77.71, 77.8 ,
78. , 78.03, 78.4 , 78.5 , 78.6 , 78.9 , 79. , 79.2 ,
79.28, 79.3 , 79.34, 79.4 , 79.42, 79.5 , 79.7 , 79.74,
80. , 80.1 , 80.2 , 80.3 , 80.39, 80.5 , 80.62, 80.7 ,
80.8 , 80.9 , 81. , 81.1 , 81.3 , 81.4 , 81.5 , 81.6 ,
81.66, 81.7 , 81.9 , 82. , 82.05, 82.1 , 82.2 , 82.3 ,
82.4 , 82.55, 82.8 , 82.9 , 83. , 83.2 , 83.5 , 83.6 ,
83.7 , 83.8 , 84. , 84.1 , 84.2 , 84.5 , 84.6 , 84.69,
84.7 , 85. , 85.1 , 85.2 , 85.3 , 85.6 , 86. , 86.1 ,
86.2 , 86.6 , 86.7 , 87. , 87.2 , 87.23, 87.5 , 87.7 ,
87.8 , 88. , 88.1 , 88.2 , 88.3 , 89. , 89.1 , 89.11,
89.2 , 89.3 , 89.4 , 89.5 , 89.6 , 89.7 , 89.9 , 90. ,
90.2 , 90.6 , 90.7 , 91. , 91.2 , 91.24, 91.7 , 91.77,
91.8 , 92. , 92.1 , 92.3 , 92.34, 92.5 , 92.6 , 92.7 ,
92.8 , 92.9 , 93. , 93.1 , 93.2 , 93.5 , 93.6 , 94. ,
94.1 , 94.4 , 94.54, 94.8 , 94.89, 94.9 , 95. , 95.1 ,
95.2 , 95.4 , 95.41, 95.45, 95.6 , 95.7 , 95.9 , 96. ,
96.3 , 96.4 , 96.6 , 96.7 , 97. , 97.2 , 97.3 , 97.6 ,
98. , 98.2 , 98.5 , 98.7 , 98.9 , 99. , 99.1 , 99.21,
99.3 , 99.5 , 99.6 , 99.7 , 99.8 , 99.9 , 100. , 100.1 ,
100.23, 100.4 , 100.7 , 100.9 , 101. , 101.2 , 101.54, 101.82,
102. , 102.2 , 102.3 , 102.5 , 102.8 , 103. , 103.1 , 103.3 ,
103.6 , 103.7 , 103.8 , 104. , 104.1 , 104.2 , 104.76, 104.8 ,
105. , 105.3 , 105.8 , 106. , 106.1 , 106.2 , 106.4 , 106.5 ,
107. , 107.03, 107.6 , 108. , 108.8 , 109. , 109.4 , 109.51,
110. , 110.3 , 110.4 , 110.8 , 111. , 111.1 , 111.6 , 111.86,
112. , 112.2 , 112.4 , 112.7 , 113. , 114. , 114.7 , 114.8 ,
115. , 115.5 , 115.8 , 116. , 116.2 , 117. , 117.1 , 117.3 ,
117.4 , 118.4 , 118.5 , 118.9 , 119. , 119.3 , 119.5 , 119.9 ,
120. , 121. , 121.6 , 122. , 122.1 , 123. , 123.1 , 123.27,
123.6 , 123.9 , 124. , 124.9 , 125. , 125.1 , 125.5 , 125.7 ,
125.9 , 126. , 126.4 , 126.6 , 127. , 127.7 , 128. , 129. ,
130. , 130.3 , 131. , 131.5 , 132. , 133. , 133.4 , 134. ,
134.7 , 134.8 , 136. , 136.1 , 136.2 , 137.7 , 138.8 , 139. ,
139.4 , 139.8 , 140. , 141. , 142. , 143. , 144.5 , 144.6 ,
145. , 145.4 , 145.5 , 145.9 , 147. , 147.2 , 148. , 148.6 ,
149.4 , 150. , 150.4 , 150.8 , 151. , 151.1 , 151.4 , 151.6 ,
152. , 153. , 153.9 , 154. , 154.7 , 155. , 155.1 , 155.5 ,
157. , 159.2 , 159.5 , 159.6 , 159.9 , 160. , 160.1 , 160.6 ,
161.4 , 162. , 163.2 , 163.5 , 164.3 , 164.7 , 165. , 165.5 ,
166.7 , 167. , 168.3 , 170. , 170.8 , 171. , 174. , 174.3 ,
175. , 176.2 , 176.6 , 177. , 177.3 , 179. , 179.2 , 180. ,
181.8 , 182. , 182.8 , 183. , 183.7 , 184. , 184.9 , 187. ,
187.9 , 188.7 , 189.4 , 190. , 193. , 193.5 , 194. , 195. ,
198. , 199. , 200. , 204. , 211. , 216. , 218. , 220. ,
222. , 225.9 , 230. , 239.4 , 248.5 , 248.7 , 250. , 255.7 ,
258. , 260. , 264.5 , 274. , 279.6 , 300. , 301.5 , 312.5 ,
322.3 , 332. , 347.5 , 409. , 409.7 , nan])
Теперь значения жилой площади соответствуют установленной точности определения.
Обзор значений
Среди значений жилой площади можно заметить подозрительно маленькие величины — менее 6 м². Рассмотрим записи, в которых жилая площадь объекта недвижимости составляет менее 9 м².
columns = ['total_area', 'living_area', 'kitchen_area', 'studio', 'rooms',
'floors_total', 'locality_name', 'city_centers_nearest',
'airports_nearest']
data[columns][data['living_area'] < 9].sort_values(by='living_area')
| total_area | living_area | kitchen_area | studio | rooms | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 13915 | 52.0 | 2.0 | 9.0 | False | 2 | 6.0 | Санкт-Петербург | 6521.0 | 32453.0 |
| 21758 | 23.0 | 2.0 | NaN | True | 0 | 24.0 | Мурино | NaN | NaN |
| 3242 | 41.0 | 3.0 | 11.0 | False | 1 | 17.0 | Санкт-Петербург | 13073.0 | 19272.0 |
| 23574 | 139.0 | 3.0 | 16.0 | False | 3 | 8.0 | Санкт-Петербург | 5975.0 | 33255.0 |
| 17582 | 22.0 | 5.0 | NaN | True | 0 | 25.0 | Санкт-Петербург | 11618.0 | 22735.0 |
| 21943 | 77.6 | 5.4 | 9.8 | False | 4 | 9.0 | Санкт-Петербург | 11270.0 | 29338.0 |
| 16431 | 31.0 | 6.0 | 17.0 | False | 1 | 5.0 | Санкт-Петербург | 4826.0 | 32177.0 |
| 19251 | 33.0 | 6.5 | 18.0 | False | 1 | 22.0 | Санкт-Петербург | 10592.0 | 9258.0 |
| 20994 | 50.6 | 8.0 | 31.0 | False | 2 | 7.0 | Санкт-Петербург | 8301.0 | 12771.0 |
| 23208 | 37.0 | 8.0 | 22.0 | False | 1 | 14.0 | Санкт-Петербург | 12387.0 | 27838.0 |
| 114 | 21.4 | 8.3 | 6.3 | False | 1 | 8.0 | Санкт-Петербург | 5791.0 | 27089.0 |
| 2309 | 62.4 | 8.4 | 41.0 | False | 2 | 9.0 | Шушары | 29448.0 | 23662.0 |
| 21505 | 35.3 | 8.5 | 16.1 | False | 1 | 27.0 | Санкт-Петербург | 15076.0 | 33977.0 |
| 17248 | 33.0 | 8.9 | 16.1 | False | 1 | 22.0 | Санкт-Петербург | 13671.0 | 33803.0 |
Всего имеется шесть записей, в которых жилая площадь составляет менее 6 м². Среди них две записи относятся к квартирам-студиям, а четыре — к обычным квартирам. Записи об обычных квартирах тем более представляются сомнительными, поскольку в трёх объектах из четырёх количество жилых комнат превышает 1.
Редактирование значений
В наборе данных имеются записи схожие с записями об объектах недвижимости, у которых жилая площадь меньше 6 м² и которые не позиционируются как квартиры-студии.
Запись № 13915. Объект недвижимости расположен на расстоянии 6521 м от центра Санкт-Петербурга. Найдём объекты, удалённые на таком же расстоянии.
data[columns][data['city_centers_nearest'] == 6521]
| total_area | living_area | kitchen_area | studio | rooms | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 13915 | 52.0 | 2.0 | 9.0 | False | 2 | 6.0 | Санкт-Петербург | 6521.0 | 32453.0 |
| 17058 | 48.0 | 26.0 | 8.0 | False | 2 | 5.0 | Санкт-Петербург | 6521.0 | 32453.0 |
Вероятно, была потеряна первая цифра в значении жилой площади. Заменим 2 м² на 22 м².
data.loc[13915, 'living_area'] = 22
data.loc[[13915], columns]
| total_area | living_area | kitchen_area | studio | rooms | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 13915 | 52.0 | 22.0 | 9.0 | False | 2 | 6.0 | Санкт-Петербург | 6521.0 | 32453.0 |
Запись № 3242. Объект недвижимости расположен на расстоянии 13 073 м от центра Санкт-Петербурга, на расстоянии 19 272 м от аэропорта в 17-этажном здании. Найдём объекты со схожими параметрами.
data[columns][(data['city_centers_nearest'] == 13073) &
(data['airports_nearest'] == 19272) &
(data['floors_total'] == 17)]
| total_area | living_area | kitchen_area | studio | rooms | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 796 | 36.0 | 16.5 | 10.0 | False | 1 | 17.0 | Санкт-Петербург | 13073.0 | 19272.0 |
| 3242 | 41.0 | 3.0 | 11.0 | False | 1 | 17.0 | Санкт-Петербург | 13073.0 | 19272.0 |
| 6890 | 55.0 | 35.0 | 10.0 | False | 2 | 17.0 | Санкт-Петербург | 13073.0 | 19272.0 |
| 12084 | 57.0 | 33.0 | 11.0 | False | 2 | 17.0 | Санкт-Петербург | 13073.0 | 19272.0 |
| 16530 | 66.0 | 35.8 | 10.6 | False | 2 | 17.0 | Санкт-Петербург | 13073.0 | 19272.0 |
| 22545 | 81.4 | 45.4 | 11.5 | False | 3 | 17.0 | Санкт-Петербург | 13073.0 | 19272.0 |
Схожим по данным является объект в записи № 796. Возможно, пропала первая цифра в значении жилой площади.
Заменим 3 м² на 13 м².
data.loc[3242, 'living_area'] = 13
data.loc[[3242], columns]
| total_area | living_area | kitchen_area | studio | rooms | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 3242 | 41.0 | 13.0 | 11.0 | False | 1 | 17.0 | Санкт-Петербург | 13073.0 | 19272.0 |
Запись № 23574. Объект недвижимости расположен на расстоянии 5975 м от центра Санкт-Петербурга. Найдём объекты, удалённые на таком же расстоянии.
data[columns][data['city_centers_nearest'] == 5975]
| total_area | living_area | kitchen_area | studio | rooms | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 411 | 151.0 | 85.0 | 23.0 | False | 3 | 8.0 | Санкт-Петербург | 5975.0 | 33255.0 |
| 3056 | 143.0 | 83.5 | 19.4 | False | 2 | 8.0 | Санкт-Петербург | 5975.0 | 33255.0 |
| 23574 | 139.0 | 3.0 | 16.0 | False | 3 | 8.0 | Санкт-Петербург | 5975.0 | 33255.0 |
Объекты недвижимости находятся либо в одном здании, либо в соседних 8-этажных зданиях. Вероятно, потерялась первая цифра (цифра 8) в значении жилой площади. Заменим 3 м² на 83 м².
data.loc[23574, 'living_area'] = 83
data.loc[[23574], columns]
| total_area | living_area | kitchen_area | studio | rooms | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 23574 | 139.0 | 83.0 | 16.0 | False | 3 | 8.0 | Санкт-Петербург | 5975.0 | 33255.0 |
Запись № 21943. Объект недвижимости расположен на расстоянии 11 270 м от центра Санкт-Петербурга. Найдём объекты, удалённые на таком же расстоянии.
data[columns][data['city_centers_nearest'] == 11270]
| total_area | living_area | kitchen_area | studio | rooms | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 6143 | 50.3 | NaN | 6.9 | False | 2 | 9.0 | Санкт-Петербург | 11270.0 | 29338.0 |
| 6667 | 50.4 | 30.3 | 9.5 | False | 2 | 9.0 | Санкт-Петербург | 11270.0 | 29338.0 |
| 11414 | 62.4 | 40.0 | 9.5 | False | 3 | 9.0 | Санкт-Петербург | 11270.0 | 29338.0 |
| 19873 | 50.3 | 28.3 | 7.0 | False | 2 | 9.0 | Санкт-Петербург | 11270.0 | 29338.0 |
| 21943 | 77.6 | 5.4 | 9.8 | False | 4 | 9.0 | Санкт-Петербург | 11270.0 | 29338.0 |
Поскольку в объекте недвижимости находятся 4 жилые комнаты, можно предположить, что в значении жилой площади положение запятой, отделяющей десятичную часть, сместилось на один знак влево. Заменим 5,4 м² на 54 м².
data.loc[21943, 'living_area'] = 54
data.loc[[21943], columns]
| total_area | living_area | kitchen_area | studio | rooms | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 21943 | 77.6 | 54.0 | 9.8 | False | 4 | 9.0 | Санкт-Петербург | 11270.0 | 29338.0 |
Запись № 17582. Объект недвижимости расположен на расстоянии 11 270 м от центра Санкт-Петербурга в 25-этажном здании. Найдём объекты со схожими параметрами.
data[columns][(data['city_centers_nearest'] == 11618) &
(data['floors_total'] == 25)]
| total_area | living_area | kitchen_area | studio | rooms | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 959 | 35.0 | NaN | NaN | False | 1 | 25.0 | Санкт-Петербург | 11618.0 | 22735.0 |
| 7288 | 40.0 | 18.0 | 8.0 | False | 1 | 25.0 | Санкт-Петербург | 11618.0 | 22735.0 |
| 13574 | 38.9 | 17.4 | 11.9 | False | 1 | 25.0 | Санкт-Петербург | 11618.0 | 22735.0 |
| 17582 | 22.0 | 5.0 | NaN | True | 0 | 25.0 | Санкт-Петербург | 11618.0 | 22735.0 |
| 21504 | 65.5 | 24.0 | 20.9 | False | 2 | 25.0 | Санкт-Петербург | 11618.0 | 22735.0 |
| 23111 | 26.1 | 16.0 | NaN | False | 1 | 25.0 | Санкт-Петербург | 11618.0 | 22735.0 |
Схожим является объект в записи № 23111. Возможно, в значении жилой площади также была потеряна первая цифра.
Заменим 5 м² на 15 м².
data.loc[17582, 'living_area'] = 15
data.loc[[17582], columns]
| total_area | living_area | kitchen_area | studio | rooms | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 17582 | 22.0 | 15.0 | NaN | True | 0 | 25.0 | Санкт-Петербург | 11618.0 | 22735.0 |
Запись № 21758. Объект недвижимости является квартирой-студией, расположен в Мурино в 24-этажном здании. Найдём объекты со схожими параметрами.
data[columns][(data['locality_name'] == 'Мурино') &
data['studio'] &
(data['floors_total'] == 24)]
| total_area | living_area | kitchen_area | studio | rooms | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 144 | 27.0 | 15.50 | NaN | True | 0 | 24.0 | Мурино | NaN | NaN |
| 15109 | 24.4 | 13.56 | NaN | True | 0 | 24.0 | Мурино | NaN | NaN |
| 21758 | 23.0 | 2.00 | NaN | True | 0 | 24.0 | Мурино | NaN | NaN |
Вероятно, и в этом случае была утеряна первая цифра в значении жилой площади. Заменим 2 м² на 12 м².
data.loc[21758, 'living_area'] = 12
data.loc[[21758], columns]
| total_area | living_area | kitchen_area | studio | rooms | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 21758 | 23.0 | 12.0 | NaN | True | 0 | 24.0 | Мурино | NaN | NaN |
data['living_area'].sort_values().unique()
array([ 6. , 6.5 , 8. , 8.3 , 8.4 , 8.5 , 8.9 , 9. ,
9.1 , 9.8 , 10. , 10.08, 10.3 , 10.4 , 10.5 , 10.52,
10.55, 10.6 , 10.7 , 10.76, 10.8 , 10.9 , 10.93, 10.94,
11. , 11.1 , 11.15, 11.2 , 11.3 , 11.38, 11.4 , 11.47,
11.5 , 11.6 , 11.7 , 11.79, 11.88, 11.9 , 11.99, 12. ,
12.08, 12.1 , 12.18, 12.2 , 12.28, 12.3 , 12.5 , 12.6 ,
12.7 , 12.71, 12.79, 12.8 , 12.81, 12.9 , 13. , 13.05,
13.09, 13.1 , 13.15, 13.2 , 13.27, 13.3 , 13.32, 13.34,
13.37, 13.4 , 13.46, 13.5 , 13.54, 13.56, 13.59, 13.6 ,
13.62, 13.66, 13.7 , 13.73, 13.76, 13.79, 13.8 , 13.82,
13.89, 13.9 , 13.92, 14. , 14.01, 14.02, 14.03, 14.06,
14.08, 14.1 , 14.11, 14.16, 14.17, 14.19, 14.2 , 14.22,
14.23, 14.25, 14.28, 14.3 , 14.31, 14.35, 14.37, 14.38,
14.39, 14.4 , 14.41, 14.45, 14.46, 14.47, 14.5 , 14.51,
14.55, 14.56, 14.57, 14.58, 14.59, 14.6 , 14.62, 14.64,
14.65, 14.69, 14.7 , 14.71, 14.73, 14.74, 14.77, 14.8 ,
14.85, 14.89, 14.9 , 14.91, 14.92, 14.95, 15. , 15.01,
15.02, 15.03, 15.04, 15.05, 15.06, 15.07, 15.08, 15.1 ,
15.11, 15.12, 15.13, 15.15, 15.16, 15.18, 15.2 , 15.25,
15.26, 15.3 , 15.31, 15.32, 15.33, 15.34, 15.35, 15.36,
15.37, 15.38, 15.4 , 15.41, 15.42, 15.43, 15.45, 15.46,
15.5 , 15.53, 15.54, 15.55, 15.58, 15.6 , 15.61, 15.62,
15.64, 15.65, 15.66, 15.7 , 15.71, 15.72, 15.77, 15.78,
15.79, 15.8 , 15.82, 15.85, 15.86, 15.88, 15.89, 15.9 ,
15.91, 15.92, 15.93, 15.96, 16. , 16.04, 16.06, 16.07,
16.08, 16.09, 16.1 , 16.11, 16.12, 16.15, 16.16, 16.18,
16.2 , 16.22, 16.26, 16.29, 16.3 , 16.31, 16.32, 16.4 ,
16.41, 16.42, 16.47, 16.5 , 16.51, 16.52, 16.55, 16.58,
16.59, 16.6 , 16.61, 16.62, 16.63, 16.66, 16.68, 16.69,
16.7 , 16.71, 16.72, 16.74, 16.76, 16.8 , 16.83, 16.84,
16.88, 16.9 , 16.91, 16.92, 16.93, 16.94, 16.95, 16.96,
16.97, 16.98, 17. , 17.01, 17.03, 17.04, 17.05, 17.07,
17.08, 17.1 , 17.11, 17.12, 17.14, 17.19, 17.2 , 17.22,
17.25, 17.26, 17.27, 17.3 , 17.33, 17.34, 17.35, 17.36,
17.38, 17.4 , 17.43, 17.45, 17.48, 17.49, 17.5 , 17.51,
17.53, 17.6 , 17.62, 17.65, 17.66, 17.7 , 17.71, 17.73,
17.78, 17.8 , 17.82, 17.83, 17.84, 17.85, 17.87, 17.9 ,
17.92, 17.93, 17.95, 17.97, 18. , 18.02, 18.03, 18.04,
18.08, 18.09, 18.1 , 18.11, 18.12, 18.14, 18.15, 18.16,
18.19, 18.2 , 18.23, 18.28, 18.3 , 18.33, 18.34, 18.35,
18.39, 18.4 , 18.44, 18.46, 18.47, 18.5 , 18.55, 18.57,
18.6 , 18.61, 18.62, 18.7 , 18.72, 18.79, 18.8 , 18.83,
18.84, 18.86, 18.88, 18.9 , 18.93, 18.95, 19. , 19.03,
19.1 , 19.15, 19.2 , 19.22, 19.3 , 19.35, 19.4 , 19.5 ,
19.52, 19.55, 19.6 , 19.65, 19.7 , 19.8 , 19.9 , 19.95,
20. , 20.02, 20.03, 20.1 , 20.11, 20.13, 20.19, 20.2 ,
20.26, 20.3 , 20.31, 20.36, 20.39, 20.4 , 20.46, 20.5 ,
20.52, 20.55, 20.6 , 20.67, 20.7 , 20.74, 20.75, 20.77,
20.8 , 20.9 , 20.97, 21. , 21.04, 21.06, 21.08, 21.09,
21.1 , 21.11, 21.12, 21.15, 21.2 , 21.28, 21.3 , 21.4 ,
21.5 , 21.53, 21.59, 21.6 , 21.65, 21.68, 21.7 , 21.77,
21.8 , 21.9 , 22. , 22.04, 22.1 , 22.15, 22.2 , 22.3 ,
22.35, 22.37, 22.4 , 22.43, 22.45, 22.5 , 22.57, 22.6 ,
22.62, 22.7 , 22.8 , 22.81, 22.9 , 23. , 23.1 , 23.19,
23.2 , 23.3 , 23.4 , 23.43, 23.5 , 23.6 , 23.7 , 23.77,
23.8 , 23.9 , 24. , 24.1 , 24.2 , 24.3 , 24.4 , 24.42,
24.5 , 24.6 , 24.64, 24.7 , 24.75, 24.77, 24.8 , 24.83,
24.86, 24.89, 24.9 , 25. , 25.1 , 25.2 , 25.3 , 25.38,
25.4 , 25.41, 25.44, 25.5 , 25.6 , 25.7 , 25.8 , 25.81,
25.9 , 25.95, 25.97, 26. , 26.1 , 26.13, 26.2 , 26.21,
26.28, 26.29, 26.3 , 26.4 , 26.5 , 26.51, 26.6 , 26.61,
26.7 , 26.75, 26.79, 26.8 , 26.87, 26.9 , 26.94, 27. ,
27.05, 27.06, 27.1 , 27.12, 27.2 , 27.22, 27.25, 27.29,
27.3 , 27.33, 27.38, 27.4 , 27.42, 27.43, 27.46, 27.5 ,
27.51, 27.57, 27.6 , 27.67, 27.69, 27.7 , 27.75, 27.77,
27.8 , 27.88, 27.89, 27.9 , 27.92, 27.95, 28. , 28.01,
28.02, 28.07, 28.09, 28.1 , 28.14, 28.15, 28.18, 28.2 ,
28.23, 28.26, 28.3 , 28.31, 28.33, 28.34, 28.36, 28.4 ,
28.42, 28.43, 28.45, 28.47, 28.48, 28.5 , 28.54, 28.55,
28.6 , 28.66, 28.7 , 28.71, 28.73, 28.77, 28.8 , 28.81,
28.84, 28.85, 28.86, 28.88, 28.9 , 28.98, 29. , 29.01,
29.08, 29.1 , 29.13, 29.16, 29.2 , 29.21, 29.22, 29.27,
29.3 , 29.34, 29.38, 29.4 , 29.41, 29.43, 29.48, 29.5 ,
29.52, 29.55, 29.56, 29.6 , 29.61, 29.67, 29.7 , 29.72,
29.74, 29.77, 29.78, 29.8 , 29.81, 29.83, 29.84, 29.85,
29.9 , 29.92, 30. , 30.01, 30.04, 30.05, 30.08, 30.1 ,
30.12, 30.15, 30.16, 30.17, 30.2 , 30.29, 30.3 , 30.31,
30.35, 30.39, 30.4 , 30.5 , 30.52, 30.55, 30.57, 30.59,
30.6 , 30.61, 30.62, 30.7 , 30.72, 30.75, 30.8 , 30.81,
30.82, 30.83, 30.89, 30.9 , 30.92, 31. , 31.01, 31.04,
31.05, 31.07, 31.1 , 31.12, 31.18, 31.2 , 31.26, 31.29,
31.3 , 31.38, 31.4 , 31.41, 31.42, 31.43, 31.44, 31.47,
31.48, 31.5 , 31.51, 31.52, 31.55, 31.6 , 31.61, 31.62,
31.64, 31.65, 31.7 , 31.71, 31.74, 31.77, 31.8 , 31.81,
31.9 , 32. , 32.02, 32.04, 32.05, 32.06, 32.08, 32.1 ,
32.2 , 32.26, 32.3 , 32.35, 32.37, 32.38, 32.4 , 32.46,
32.5 , 32.6 , 32.61, 32.62, 32.7 , 32.71, 32.73, 32.79,
32.8 , 32.84, 32.9 , 32.95, 33. , 33.03, 33.06, 33.08,
33.1 , 33.18, 33.2 , 33.26, 33.3 , 33.36, 33.4 , 33.47,
33.5 , 33.57, 33.6 , 33.63, 33.67, 33.7 , 33.72, 33.73,
33.8 , 33.87, 33.9 , 33.92, 34. , 34.1 , 34.14, 34.2 ,
34.29, 34.3 , 34.32, 34.37, 34.4 , 34.41, 34.44, 34.5 ,
34.51, 34.6 , 34.63, 34.7 , 34.76, 34.79, 34.8 , 34.87,
34.88, 34.9 , 35. , 35.01, 35.05, 35.07, 35.1 , 35.17,
35.2 , 35.3 , 35.33, 35.38, 35.4 , 35.48, 35.5 , 35.55,
35.6 , 35.61, 35.7 , 35.74, 35.76, 35.77, 35.8 , 35.81,
35.88, 35.89, 35.9 , 35.91, 35.92, 36. , 36.04, 36.07,
36.1 , 36.15, 36.2 , 36.27, 36.3 , 36.35, 36.4 , 36.45,
36.5 , 36.57, 36.6 , 36.7 , 36.76, 36.79, 36.8 , 36.81,
36.86, 36.9 , 36.95, 37. , 37.1 , 37.13, 37.2 , 37.28,
37.3 , 37.4 , 37.5 , 37.52, 37.6 , 37.66, 37.7 , 37.74,
37.8 , 37.9 , 38. , 38.03, 38.05, 38.07, 38.1 , 38.18,
38.2 , 38.3 , 38.33, 38.39, 38.4 , 38.5 , 38.6 , 38.7 ,
38.73, 38.8 , 38.9 , 38.91, 38.95, 38.99, 39. , 39.07,
39.1 , 39.18, 39.2 , 39.3 , 39.4 , 39.41, 39.5 , 39.59,
39.6 , 39.62, 39.66, 39.7 , 39.71, 39.78, 39.8 , 39.85,
39.9 , 40. , 40.06, 40.1 , 40.2 , 40.3 , 40.32, 40.39,
40.4 , 40.43, 40.5 , 40.57, 40.59, 40.6 , 40.61, 40.7 ,
40.79, 40.8 , 40.83, 40.9 , 40.92, 40.95, 41. , 41.05,
41.06, 41.08, 41.1 , 41.17, 41.19, 41.2 , 41.3 , 41.34,
41.35, 41.4 , 41.44, 41.5 , 41.6 , 41.69, 41.7 , 41.8 ,
41.9 , 41.92, 41.98, 42. , 42.1 , 42.17, 42.2 , 42.26,
42.3 , 42.31, 42.4 , 42.41, 42.43, 42.48, 42.5 , 42.54,
42.55, 42.6 , 42.7 , 42.8 , 42.9 , 42.91, 43. , 43.05,
43.1 , 43.15, 43.2 , 43.3 , 43.32, 43.4 , 43.45, 43.46,
43.5 , 43.6 , 43.62, 43.63, 43.7 , 43.71, 43.78, 43.8 ,
43.81, 43.83, 43.89, 43.9 , 43.92, 44. , 44.04, 44.05,
44.1 , 44.13, 44.15, 44.2 , 44.3 , 44.4 , 44.5 , 44.56,
44.6 , 44.7 , 44.8 , 44.9 , 44.91, 44.99, 45. , 45.1 ,
45.11, 45.13, 45.18, 45.2 , 45.23, 45.3 , 45.34, 45.38,
45.4 , 45.5 , 45.6 , 45.7 , 45.72, 45.8 , 45.82, 45.85,
45.86, 45.9 , 45.92, 45.95, 46. , 46.01, 46.05, 46.1 ,
46.13, 46.14, 46.15, 46.2 , 46.3 , 46.4 , 46.5 , 46.57,
46.6 , 46.64, 46.7 , 46.75, 46.8 , 46.9 , 47. , 47.1 ,
47.11, 47.2 , 47.24, 47.3 , 47.37, 47.4 , 47.43, 47.5 ,
47.53, 47.6 , 47.68, 47.7 , 47.8 , 47.9 , 48. , 48.05,
48.1 , 48.13, 48.2 , 48.25, 48.3 , 48.35, 48.36, 48.38,
48.4 , 48.41, 48.42, 48.45, 48.46, 48.48, 48.49, 48.5 ,
48.6 , 48.62, 48.7 , 48.8 , 48.84, 48.88, 48.9 , 48.93,
48.94, 49. , 49.1 , 49.2 , 49.25, 49.27, 49.28, 49.3 ,
49.33, 49.4 , 49.46, 49.5 , 49.58, 49.6 , 49.7 , 49.74,
49.8 , 49.87, 49.9 , 49.98, 50. , 50.02, 50.08, 50.1 ,
50.16, 50.2 , 50.25, 50.26, 50.28, 50.3 , 50.34, 50.4 ,
50.47, 50.5 , 50.6 , 50.64, 50.7 , 50.8 , 50.81, 50.9 ,
51. , 51.07, 51.1 , 51.2 , 51.3 , 51.4 , 51.5 , 51.6 ,
51.7 , 51.76, 51.78, 51.8 , 51.88, 51.9 , 52. , 52.02,
52.1 , 52.2 , 52.21, 52.26, 52.3 , 52.4 , 52.5 , 52.53,
52.6 , 52.65, 52.7 , 52.77, 52.8 , 52.9 , 52.94, 53. ,
53.1 , 53.15, 53.17, 53.2 , 53.3 , 53.31, 53.33, 53.35,
53.4 , 53.5 , 53.6 , 53.7 , 53.8 , 53.9 , 54. , 54.09,
54.1 , 54.13, 54.2 , 54.3 , 54.4 , 54.43, 54.48, 54.5 ,
54.6 , 54.7 , 54.74, 54.8 , 54.9 , 55. , 55.1 , 55.2 ,
55.22, 55.3 , 55.35, 55.38, 55.4 , 55.5 , 55.6 , 55.7 ,
55.8 , 55.84, 55.9 , 56. , 56.1 , 56.12, 56.2 , 56.3 ,
56.4 , 56.5 , 56.53, 56.6 , 56.7 , 56.8 , 56.86, 56.9 ,
57. , 57.1 , 57.2 , 57.3 , 57.35, 57.4 , 57.5 , 57.51,
57.6 , 57.7 , 57.75, 57.8 , 57.9 , 58. , 58.1 , 58.18,
58.2 , 58.3 , 58.4 , 58.44, 58.5 , 58.6 , 58.63, 58.7 ,
58.8 , 58.82, 59. , 59.1 , 59.12, 59.2 , 59.3 , 59.4 ,
59.5 , 59.6 , 59.7 , 59.8 , 59.9 , 60. , 60.1 , 60.2 ,
60.3 , 60.33, 60.4 , 60.5 , 60.6 , 60.7 , 60.77, 60.8 ,
60.9 , 61. , 61.1 , 61.2 , 61.3 , 61.35, 61.4 , 61.5 ,
61.6 , 61.7 , 61.8 , 61.9 , 62. , 62.1 , 62.2 , 62.3 ,
62.4 , 62.5 , 62.6 , 62.7 , 62.75, 62.8 , 62.9 , 63. ,
63.1 , 63.2 , 63.3 , 63.31, 63.4 , 63.5 , 63.6 , 63.7 ,
63.72, 63.8 , 63.9 , 64. , 64.1 , 64.2 , 64.3 , 64.32,
64.4 , 64.5 , 64.6 , 64.7 , 64.8 , 64.9 , 65. , 65.3 ,
65.4 , 65.5 , 65.6 , 65.7 , 65.72, 65.8 , 65.9 , 65.93,
66. , 66.01, 66.1 , 66.2 , 66.22, 66.24, 66.3 , 66.4 ,
66.5 , 66.6 , 66.7 , 66.8 , 66.9 , 66.99, 67. , 67.01,
67.1 , 67.2 , 67.3 , 67.4 , 67.5 , 67.6 , 67.8 , 67.81,
67.9 , 68. , 68.1 , 68.3 , 68.4 , 68.48, 68.5 , 68.6 ,
68.7 , 68.8 , 68.9 , 69. , 69.1 , 69.2 , 69.28, 69.3 ,
69.5 , 69.6 , 69.7 , 69.75, 69.8 , 69.9 , 70. , 70.1 ,
70.3 , 70.4 , 70.48, 70.5 , 70.6 , 70.7 , 70.9 , 71. ,
71.1 , 71.2 , 71.3 , 71.4 , 71.5 , 71.7 , 71.72, 71.9 ,
72. , 72.1 , 72.2 , 72.3 , 72.4 , 72.5 , 72.52, 72.6 ,
72.7 , 72.79, 72.8 , 73. , 73.1 , 73.2 , 73.3 , 73.4 ,
73.5 , 73.6 , 73.8 , 73.9 , 74. , 74.1 , 74.16, 74.2 ,
74.3 , 74.4 , 74.6 , 74.8 , 74.99, 75. , 75.1 , 75.2 ,
75.25, 75.4 , 75.5 , 75.6 , 75.7 , 75.8 , 75.83, 76. ,
76.1 , 76.2 , 76.3 , 76.4 , 76.5 , 76.65, 76.7 , 76.8 ,
76.9 , 77. , 77.1 , 77.2 , 77.3 , 77.35, 77.4 , 77.5 ,
77.6 , 77.61, 77.71, 77.8 , 78. , 78.03, 78.4 , 78.5 ,
78.6 , 78.9 , 79. , 79.2 , 79.28, 79.3 , 79.34, 79.4 ,
79.42, 79.5 , 79.7 , 79.74, 80. , 80.1 , 80.2 , 80.3 ,
80.39, 80.5 , 80.62, 80.7 , 80.8 , 80.9 , 81. , 81.1 ,
81.3 , 81.4 , 81.5 , 81.6 , 81.66, 81.7 , 81.9 , 82. ,
82.05, 82.1 , 82.2 , 82.3 , 82.4 , 82.55, 82.8 , 82.9 ,
83. , 83.2 , 83.5 , 83.6 , 83.7 , 83.8 , 84. , 84.1 ,
84.2 , 84.5 , 84.6 , 84.69, 84.7 , 85. , 85.1 , 85.2 ,
85.3 , 85.6 , 86. , 86.1 , 86.2 , 86.6 , 86.7 , 87. ,
87.2 , 87.23, 87.5 , 87.7 , 87.8 , 88. , 88.1 , 88.2 ,
88.3 , 89. , 89.1 , 89.11, 89.2 , 89.3 , 89.4 , 89.5 ,
89.6 , 89.7 , 89.9 , 90. , 90.2 , 90.6 , 90.7 , 91. ,
91.2 , 91.24, 91.7 , 91.77, 91.8 , 92. , 92.1 , 92.3 ,
92.34, 92.5 , 92.6 , 92.7 , 92.8 , 92.9 , 93. , 93.1 ,
93.2 , 93.5 , 93.6 , 94. , 94.1 , 94.4 , 94.54, 94.8 ,
94.89, 94.9 , 95. , 95.1 , 95.2 , 95.4 , 95.41, 95.45,
95.6 , 95.7 , 95.9 , 96. , 96.3 , 96.4 , 96.6 , 96.7 ,
97. , 97.2 , 97.3 , 97.6 , 98. , 98.2 , 98.5 , 98.7 ,
98.9 , 99. , 99.1 , 99.21, 99.3 , 99.5 , 99.6 , 99.7 ,
99.8 , 99.9 , 100. , 100.1 , 100.23, 100.4 , 100.7 , 100.9 ,
101. , 101.2 , 101.54, 101.82, 102. , 102.2 , 102.3 , 102.5 ,
102.8 , 103. , 103.1 , 103.3 , 103.6 , 103.7 , 103.8 , 104. ,
104.1 , 104.2 , 104.76, 104.8 , 105. , 105.3 , 105.8 , 106. ,
106.1 , 106.2 , 106.4 , 106.5 , 107. , 107.03, 107.6 , 108. ,
108.8 , 109. , 109.4 , 109.51, 110. , 110.3 , 110.4 , 110.8 ,
111. , 111.1 , 111.6 , 111.86, 112. , 112.2 , 112.4 , 112.7 ,
113. , 114. , 114.7 , 114.8 , 115. , 115.5 , 115.8 , 116. ,
116.2 , 117. , 117.1 , 117.3 , 117.4 , 118.4 , 118.5 , 118.9 ,
119. , 119.3 , 119.5 , 119.9 , 120. , 121. , 121.6 , 122. ,
122.1 , 123. , 123.1 , 123.27, 123.6 , 123.9 , 124. , 124.9 ,
125. , 125.1 , 125.5 , 125.7 , 125.9 , 126. , 126.4 , 126.6 ,
127. , 127.7 , 128. , 129. , 130. , 130.3 , 131. , 131.5 ,
132. , 133. , 133.4 , 134. , 134.7 , 134.8 , 136. , 136.1 ,
136.2 , 137.7 , 138.8 , 139. , 139.4 , 139.8 , 140. , 141. ,
142. , 143. , 144.5 , 144.6 , 145. , 145.4 , 145.5 , 145.9 ,
147. , 147.2 , 148. , 148.6 , 149.4 , 150. , 150.4 , 150.8 ,
151. , 151.1 , 151.4 , 151.6 , 152. , 153. , 153.9 , 154. ,
154.7 , 155. , 155.1 , 155.5 , 157. , 159.2 , 159.5 , 159.6 ,
159.9 , 160. , 160.1 , 160.6 , 161.4 , 162. , 163.2 , 163.5 ,
164.3 , 164.7 , 165. , 165.5 , 166.7 , 167. , 168.3 , 170. ,
170.8 , 171. , 174. , 174.3 , 175. , 176.2 , 176.6 , 177. ,
177.3 , 179. , 179.2 , 180. , 181.8 , 182. , 182.8 , 183. ,
183.7 , 184. , 184.9 , 187. , 187.9 , 188.7 , 189.4 , 190. ,
193. , 193.5 , 194. , 195. , 198. , 199. , 200. , 204. ,
211. , 216. , 218. , 220. , 222. , 225.9 , 230. , 239.4 ,
248.5 , 248.7 , 250. , 255.7 , 258. , 260. , 264.5 , 274. ,
279.6 , 300. , 301.5 , 312.5 , 322.3 , 332. , 347.5 , 409. ,
409.7 , nan])
Жилая площадь у всех объектов недвижимости составляет не менее 6 м².
Значения жилой площади, площади кухни должны согласоваться с общей площадью объекта недвижимости. Сумма площадей помещений не может превышать общую площадь. Кроме того, сумма площадей жилых помещений и кухни не может быть равна общей площади объекта недвижимости, поскольку помимо кухни в квартире имеются и другие вспомогательные помещения.
columns = ['total_area', 'living_area', 'kitchen_area',
'rooms', 'floors_total', 'locality_name']
data[columns][(data['living_area'] + data['kitchen_area']).round(2) >= \
data['total_area']].sort_values('living_area')
| total_area | living_area | kitchen_area | rooms | floors_total | locality_name | |
|---|---|---|---|---|---|---|
| 8873 | 20.00 | 14.00 | 6.00 | 1 | 7.0 | Санкт-Петербург |
| 22869 | 25.00 | 14.00 | 11.00 | 1 | 5.0 | Санкт-Петербург |
| 10725 | 25.60 | 14.17 | 14.17 | 1 | 18.0 | Мурино |
| 7755 | 20.67 | 14.95 | 14.95 | 1 | 24.0 | Мурино |
| 2797 | 23.00 | 15.00 | 8.00 | 1 | 7.0 | Всеволожск |
| ... | ... | ... | ... | ... | ... | ... |
| 8211 | 93.00 | 82.00 | 14.50 | 3 | 16.0 | Санкт-Петербург |
| 12634 | 141.20 | 106.40 | 34.80 | 3 | 7.0 | Санкт-Петербург |
| 4293 | 156.00 | 115.00 | 41.00 | 4 | 5.0 | Санкт-Петербург |
| 12234 | 138.50 | 118.50 | 20.00 | 4 | 9.0 | Санкт-Петербург |
| 18164 | 146.80 | 128.00 | 18.80 | 3 | 16.0 | Санкт-Петербург |
135 rows × 6 columns
Таких объектов оказалось 135.
Удаление записей
Поскольку не представляется возможным выяснить, значения каких признаков (общей площади, жилой площади, площади кухни) были заполнены ошибочно, записи с несогласующимися значениями необходимо удалить.
data.drop(index=data[(data['living_area'] + data['kitchen_area']).round(2) >= \
data['total_area']].index,
inplace=True)
len(data[(data['living_area'] + data['kitchen_area']).round(2) >= \
data['total_area']])
0
Однако недостаточно потребовать, чтобы общая площадь была больше суммы площадей: жилой и кухни. Важное значение приобретает разность этих величин, поскольку она представляет собой площадь, приходящуюся на остальные вспомогательные помещения, кроме кухни. Необходимо задать пороговое значение, меньше которого не может быть разность общей площади и суммы площадей: жилой и кухни. Таким критерием может стать площадь, отведённая под вспомогательные помещения в квартирах, которые позиционируются как квартиры-студии.
data.loc[data['studio'], 'kitchen_area'].unique()
array([nan])
В объявлениях о продаже квартир-студий не указывается информация о площади кухни. В таких объектах недвижимости зачастую под кухню отводится зона на площади жилого помещения. Кухня оформляется как кухня-ниша. Однако туалет с ванной (душевой) является изолированным вспомогательным помещением.
Узнаем, какова минимальная площадь такого помещения среди опубликованных объявлений.
Заполним значения площади кухни в записях, относящихся к квартирам-студиям, значением 0.
data.loc[data['studio'], 'kitchen_area'] = data['kitchen_area'].fillna(0)
data.loc[data['studio'], 'kitchen_area'].unique()
array([0.])
Введем дополнительный признак — площадь вспомогательных помещений (без учёта площади кухни) utility_rooms_area.
data['utility_rooms_area'] = \
data['total_area'] - data['living_area'] - data['kitchen_area']
data['utility_rooms_area'] = data['utility_rooms_area'].round(2)
data.info()
<class 'pandas.core.frame.DataFrame'> Index: 23560 entries, 0 to 23698 Data columns (total 24 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 total_images 23560 non-null int64 1 last_price 23560 non-null float64 2 total_area 23560 non-null float64 3 first_day_exposition 23560 non-null object 4 rooms 23560 non-null int64 5 ceiling_height 14417 non-null float64 6 floors_total 23474 non-null float64 7 living_area 21657 non-null float64 8 floor 23560 non-null int64 9 is_apartment 2747 non-null object 10 studio 23560 non-null bool 11 open_plan 23560 non-null bool 12 kitchen_area 21432 non-null float64 13 balcony 12100 non-null float64 14 locality_name 23511 non-null object 15 airports_nearest 18070 non-null float64 16 city_centers_nearest 18093 non-null float64 17 parks_around_3000 18094 non-null float64 18 parks_nearest 8037 non-null float64 19 ponds_around_3000 18094 non-null float64 20 ponds_nearest 9076 non-null float64 21 days_exposition 20396 non-null float64 22 locality_type 23511 non-null object 23 utility_rooms_area 20983 non-null float64 dtypes: bool(2), float64(15), int64(3), object(4) memory usage: 4.7+ MB
Выведем записи о квартирах-студиях, которые характеризуются минимальным значением признака utility_rooms_area.
columns = ['total_area', 'living_area', 'kitchen_area', 'rooms', 'studio',
'floors_total', 'locality_name', 'utility_rooms_area']
data[columns][(data['studio']) &
(data['living_area'].notna())] \
.sort_values(by='utility_rooms_area').head()
| total_area | living_area | kitchen_area | rooms | studio | floors_total | locality_name | utility_rooms_area | |
|---|---|---|---|---|---|---|---|---|
| 12996 | 18.00 | 16.00 | 0.0 | 0 | True | 5.0 | Санкт-Петербург | 2.00 |
| 440 | 27.11 | 24.75 | 0.0 | 0 | True | 17.0 | Санкт-Петербург | 2.36 |
| 8683 | 32.50 | 29.90 | 0.0 | 1 | True | 23.0 | Санкт-Петербург | 2.60 |
| 8755 | 18.80 | 15.80 | 0.0 | 0 | True | 19.0 | Санкт-Петербург | 3.00 |
| 6225 | 28.00 | 25.00 | 0.0 | 0 | True | 25.0 | Санкт-Петербург | 3.00 |
Значения признака utility_rooms_area для квартир-студий начинаются с 2 м². Это означает, что минимальная площадь, которую требуется отвести под помещение туалета и ванной (душевой), должна составлять не менее 2 м².
Установим критерий, что площадь вспомогательных помещений (кроме кухни) не может быть меньше 2 м². Обоснованность этого критерия заключается ещё и в том, что могут существовать квартиры, в которых была осуществлена перепланировка: расширена жилая площадь и площадь кухни. Однако в связи с тем, что помещение туалета и ванной (душевой) должно быть изолировано, ожидается, что в квартире будет отведено под него помещение хотя бы минимальной площади, как это может быть сделано в квартире-студии.
Обзор значений
Проверим, есть ли объекты недвижимости, которые не удовлетворяют установленному критерию.
data[columns][data['utility_rooms_area'] < 2].sort_values('utility_rooms_area')
| total_area | living_area | kitchen_area | rooms | studio | floors_total | locality_name | utility_rooms_area | |
|---|---|---|---|---|---|---|---|---|
| 14352 | 35.20 | 29.00 | 6.00 | 1 | False | 9.0 | Выборг | 0.20 |
| 10453 | 38.00 | 30.00 | 7.78 | 1 | False | 5.0 | Санкт-Петербург | 0.22 |
| 23108 | 33.95 | 21.68 | 12.00 | 1 | False | 19.0 | Мурино | 0.27 |
| 12271 | 69.00 | 55.00 | 13.73 | 2 | False | 20.0 | Мурино | 0.27 |
| 9138 | 23.29 | 21.00 | 2.00 | 1 | False | 3.0 | Санкт-Петербург | 0.29 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 12900 | 76.60 | 60.00 | 15.00 | 2 | False | 17.0 | Санкт-Петербург | 1.60 |
| 14031 | 37.60 | 24.00 | 12.00 | 1 | False | 7.0 | Санкт-Петербург | 1.60 |
| 21106 | 52.10 | 44.40 | 6.00 | 3 | False | 14.0 | Санкт-Петербург | 1.70 |
| 18750 | 34.50 | 24.00 | 8.80 | 1 | False | 25.0 | Санкт-Петербург | 1.70 |
| 20661 | 31.60 | 17.80 | 12.00 | 1 | False | 12.0 | Санкт-Петербург | 1.80 |
68 rows × 8 columns
Таких объектов оказалось 68.
Удаление записей
Поскольку не представляется возможным выяснить, значения каких признаков (общей площади, жилой площади, площади кухни) были заполнены ошибочно, записи с несогласующимися значениями необходимо удалить.
data.drop(index=data[data['utility_rooms_area'] < 2].index,
inplace=True)
len(data[data['utility_rooms_area'] < 2])
0
Обзор значений
Теперь проверим, есть ли среди объектов недвижимости, не являющихся квартирами-студиями, такие объекты, у которых разница между общей площадью и жилой площадью уже меньше 2 м².
data[~data['studio'] & ((data['total_area'] - data['living_area']).round(2) < 2)]
| total_images | last_price | total_area | first_day_exposition | rooms | ceiling_height | floors_total | living_area | floor | is_apartment | studio | open_plan | kitchen_area | balcony | locality_name | airports_nearest | city_centers_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | days_exposition | locality_type | utility_rooms_area | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2959 | 9 | 2550000.0 | 32.00 | 2017-12-02T00:00:00 | 1 | NaN | 14.0 | 30.20 | 13 | False | False | False | NaN | 1.0 | Кудрово | NaN | NaN | NaN | NaN | NaN | NaN | 157.0 | деревня | NaN |
| 9861 | 10 | 2350000.0 | 25.00 | 2017-12-03T00:00:00 | 0 | NaN | 22.0 | 25.00 | 17 | NaN | False | True | NaN | 2.0 | Мурино | NaN | NaN | NaN | NaN | NaN | NaN | 13.0 | посёлок | NaN |
| 10606 | 14 | 2950000.0 | 25.27 | 2017-11-17T00:00:00 | 0 | NaN | 25.0 | 25.00 | 11 | NaN | False | True | NaN | 1.0 | Санкт-Петербург | 11405.0 | 13222.0 | 0.0 | NaN | 1.0 | 623.0 | 51.0 | город | NaN |
| 12691 | 1 | 3700000.0 | 24.20 | 2017-11-10T00:00:00 | 0 | NaN | 19.0 | 24.20 | 13 | NaN | False | True | NaN | 1.0 | Санкт-Петербург | 17837.0 | 16840.0 | 0.0 | NaN | 2.0 | 210.0 | 74.0 | город | NaN |
| 20256 | 5 | 13351000.0 | 102.70 | 2018-07-03T00:00:00 | 6 | 3.4 | 4.0 | 101.00 | 1 | NaN | False | False | NaN | NaN | Санкт-Петербург | 24477.0 | 5464.0 | 2.0 | 519.0 | 0.0 | NaN | 229.0 | город | NaN |
| 21802 | 6 | 1737000.0 | 17.78 | 2018-11-22T00:00:00 | 1 | 2.6 | 9.0 | 15.89 | 1 | NaN | False | False | NaN | NaN | Санкт-Петербург | 13289.0 | 12086.0 | 0.0 | NaN | 0.0 | NaN | 66.0 | город | NaN |
Удаление значений
Поскольку для этих записей также нет возможности установить, значения каких признаков (общей площади, жилой площади) были заполнены ошибочно, записи с несогласующимися значениями необходимо удалить.
data.drop(index=data[~data['studio'] &
((data['total_area'] - data['living_area']).round(2) < 2)].index,
inplace=True)
len(data[~data['studio'] & ((data['total_area'] - data['living_area']).round(2) < 2)])
0
А теперь удалим вспомогательный признак. Также уберём введённое значение площади кухни "0" для записей, относящихся к квартирам-студиям.
data = data.drop(columns='utility_rooms_area')
data['kitchen_area'].replace(0, np.nan, inplace=True)
data.info()
<class 'pandas.core.frame.DataFrame'> Index: 23486 entries, 0 to 23698 Data columns (total 23 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 total_images 23486 non-null int64 1 last_price 23486 non-null float64 2 total_area 23486 non-null float64 3 first_day_exposition 23486 non-null object 4 rooms 23486 non-null int64 5 ceiling_height 14374 non-null float64 6 floors_total 23400 non-null float64 7 living_area 21583 non-null float64 8 floor 23486 non-null int64 9 is_apartment 2739 non-null object 10 studio 23486 non-null bool 11 open_plan 23486 non-null bool 12 kitchen_area 21215 non-null float64 13 balcony 12068 non-null float64 14 locality_name 23437 non-null object 15 airports_nearest 18021 non-null float64 16 city_centers_nearest 18044 non-null float64 17 parks_around_3000 18045 non-null float64 18 parks_nearest 8023 non-null float64 19 ponds_around_3000 18045 non-null float64 20 ponds_nearest 9049 non-null float64 21 days_exposition 20331 non-null float64 22 locality_type 23437 non-null object dtypes: bool(2), float64(14), int64(3), object(4) memory usage: 4.0+ MB
Значения в признаках total_area, living_area и kitchen_area являются согласованными и отвечают установленному критерию.
Среди значений площади кухни есть одно подозрительно маленькое значение — 1,3 м². Для объекта недвижимости с такой площадью кухни не указано, что он является квартирой-студией. И хотя такая площадь кухни может быть реальной, всё же в качестве критерия следует установить минимальное значение площади кухни — 2 м². Именно это значение является минимальным, если не учитывать значение 1,3 м². И кухни такой площади встречаются уже в четырёх объектах недвижимости.
columns = ['total_area', 'living_area', 'kitchen_area', 'rooms',
'studio', 'floors_total', 'locality_name']
data[columns][data['living_area'].notna()].sort_values(by='kitchen_area').head(7)
| total_area | living_area | kitchen_area | rooms | studio | floors_total | locality_name | |
|---|---|---|---|---|---|---|---|
| 20217 | 28.5 | 19.5 | 1.3 | 1 | False | 14.0 | Санкт-Петербург |
| 11033 | 32.0 | 16.0 | 2.0 | 1 | False | 14.0 | Санкт-Петербург |
| 6262 | 24.0 | 16.0 | 2.0 | 2 | False | 5.0 | Санкт-Петербург |
| 906 | 27.0 | 18.0 | 2.0 | 1 | False | 23.0 | Санкт-Петербург |
| 21419 | 20.0 | 14.0 | 2.0 | 1 | False | 5.0 | Санкт-Петербург |
| 17834 | 34.7 | 15.5 | 2.3 | 1 | False | 26.0 | Мурино |
| 8729 | 18.4 | 14.0 | 2.4 | 1 | False | 3.0 | Пушкин |
Заменим значение 1,3 м² на 2 м².
data.loc[data['kitchen_area'] < 2, 'kitchen_area'] = 2
len(data.loc[data['kitchen_area'] < 2])
0
Теперь выясним, есть ли среди записей такие объекты недвижимости, у которых не указана площадь кухни, и разность общей площади и жилой площади меньше 4 м²: 2 м² — минимальное значение площади кухни, и 2 м² — минимальное значение площади вспомогательных помещений (кроме кухни).
data[~data['studio'] &
(data['rooms'] != 0) &
((data['total_area'] - data['living_area']).round(2) < 4)]
| total_images | last_price | total_area | first_day_exposition | rooms | ceiling_height | floors_total | living_area | floor | is_apartment | studio | open_plan | kitchen_area | balcony | locality_name | airports_nearest | city_centers_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | days_exposition | locality_type | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 4339 | 19 | 6900000.0 | 72.0 | 2019-03-25T00:00:00 | 3 | 3.50 | 4.0 | 70.0 | 1 | True | False | False | NaN | NaN | Санкт-Петербург | 31487.0 | 4466.0 | 2.0 | 353.0 | 1.0 | 439.0 | 22.0 | город |
| 7052 | 4 | 2650000.0 | 23.3 | 2017-11-25T00:00:00 | 1 | NaN | 12.0 | 20.0 | 10 | NaN | False | False | NaN | NaN | Санкт-Петербург | 20381.0 | 19383.0 | 0.0 | NaN | 1.0 | 579.0 | 355.0 | город |
| 9157 | 0 | 3400000.0 | 17.6 | 2018-03-18T00:00:00 | 1 | NaN | 5.0 | 15.0 | 2 | NaN | False | False | NaN | NaN | Санкт-Петербург | 21555.0 | 1967.0 | 2.0 | 336.0 | 1.0 | 309.0 | 117.0 | город |
| 19268 | 10 | 3450000.0 | 43.3 | 2018-09-18T00:00:00 | 1 | 2.75 | 18.0 | 41.3 | 7 | NaN | False | False | NaN | 2.0 | Мурино | NaN | NaN | NaN | NaN | NaN | NaN | 44.0 | посёлок |
| 19807 | 0 | 3800000.0 | 13.0 | 2018-07-04T00:00:00 | 1 | NaN | 5.0 | 10.0 | 3 | NaN | False | False | NaN | NaN | Санкт-Петербург | 21302.0 | 1242.0 | 1.0 | 592.0 | 3.0 | 27.0 | 9.0 | город |
| 19904 | 4 | 2400000.0 | 12.0 | 2017-07-19T00:00:00 | 1 | 2.55 | 5.0 | 10.0 | 2 | NaN | False | False | NaN | NaN | Санкт-Петербург | 21314.0 | 964.0 | 1.0 | 886.0 | 2.0 | 45.0 | 200.0 | город |
| 22095 | 6 | 2194000.0 | 36.5 | 2017-09-27T00:00:00 | 1 | NaN | 3.0 | 33.2 | 3 | NaN | False | False | NaN | 0.0 | Санкт-Петербург | 39446.0 | 18500.0 | 0.0 | NaN | 2.0 | 639.0 | 36.0 | город |
| 23191 | 3 | 1900000.0 | 18.9 | 2016-04-04T00:00:00 | 1 | NaN | 16.0 | 16.0 | 12 | NaN | False | False | NaN | 0.0 | Тосно | NaN | NaN | NaN | NaN | NaN | NaN | 115.0 | город |
Поскольку не представляется возможным выяснить, значения каких признаков (общей площади, жилой площади) были заполнены ошибочно, записи с несогласующимися значениями необходимо удалить.
data.drop(index=data[~data['studio'] &
(data['rooms'] != 0) &
((data['total_area'] - data['living_area']).round(2) < 4)].index,
inplace=True)
len(data[~data['studio'] &
(data['rooms'] != 0) &
((data['total_area'] - data['living_area']).round(2) < 4)])
0
Признак floors_total содержит экстремальные значения: существование в Санкт-Петербурге и Ленинградской области жилых зданий высотой 52 и 60 этажей представляется сомнительными.
data['floors_total'].sort_values(ascending=False).unique()
array([60., 52., 37., 36., 35., 34., 33., 29., 28., 27., 26., 25., 24.,
23., 22., 21., 20., 19., 18., 17., 16., 15., 14., 13., 12., 11.,
10., 9., 8., 7., 6., 5., 4., 3., 2., 1., nan])
Самым высоким жилым зданием Санкт-Петербурга и Ленинградской области является жилой комплекс "Князь Александр Невский". Здание насчитывает 35 надземных этажей (это этажность здания) и 2 подземных этажа. Таким образом, максимальное значение этажности в наборе данных может достигать значения 35. Однако в наборе данных представлены записи, в которых объекты недвижимости расположены в зданиях, имеющих этажность более 35 этажей.
Обзор значений
Выясним, где расположены здания, этажность которых превышает 35 этажей, и сколько таких зданий.
columns = ['ceiling_height', 'floor', 'floors_total', 'locality_name',
'city_centers_nearest', 'airports_nearest']
data[columns].sort_values('floors_total', ascending=False).head(8)
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 2253 | 2.88 | 4 | 60.0 | Кронштадт | 49488.0 | 67763.0 |
| 16731 | 2.65 | 18 | 52.0 | Санкт-Петербург | 12978.0 | 20728.0 |
| 16934 | 1.75 | 5 | 37.0 | Санкт-Петербург | 20444.0 | 18732.0 |
| 11079 | 2.70 | 29 | 36.0 | Санкт-Петербург | 20444.0 | 18732.0 |
| 397 | NaN | 28 | 36.0 | Санкт-Петербург | 20444.0 | 18732.0 |
| 5807 | 27.00 | 13 | 36.0 | Санкт-Петербург | 20444.0 | 18732.0 |
| 18218 | NaN | 33 | 35.0 | Санкт-Петербург | 20450.0 | 18737.0 |
| 12888 | 2.70 | 27 | 35.0 | Санкт-Петербург | 20444.0 | 18732.0 |
В наборе данных имеется шесть записей с аномальными значениями этажности. Здание высотой 60 этажей расположено в Кронштадте, а высотой 52 этажа — в Санкт-Петербурге.
Кроме того, в четырёх записях указана этажность здания 36—37 этажей. Причём на таком же расстоянии от центра Санкт-Петербурга (и от аэропорта тоже) расположено 35-этажное здание. Можно сделать вывод, что все объекты недвижимости расположены в одном здании — ЖК "Князь Александр Невский".
Редактирование значений
Запись № 2253. Найдём расположенные рядом объекты недвижимости.
data[columns][(data['locality_name'] == 'Кронштадт')].sort_values(by='floors_total')
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 15586 | 2.50 | 1 | 2.0 | Кронштадт | 50329.0 | 68604.0 |
| 2720 | 4.00 | 1 | 2.0 | Кронштадт | 50067.0 | 68341.0 |
| 72 | 2.70 | 2 | 3.0 | Кронштадт | 49984.0 | 68258.0 |
| 12846 | 3.55 | 2 | 3.0 | Кронштадт | 51136.0 | 69410.0 |
| 13995 | 3.18 | 1 | 3.0 | Кронштадт | 50282.0 | 68556.0 |
| ... | ... | ... | ... | ... | ... | ... |
| 11190 | 2.51 | 9 | 12.0 | Кронштадт | 47054.0 | 65328.0 |
| 23114 | NaN | 3 | 13.0 | Кронштадт | 46979.0 | 65254.0 |
| 8826 | NaN | 11 | 15.0 | Кронштадт | 46979.0 | 65254.0 |
| 10189 | 2.51 | 16 | 20.0 | Кронштадт | 49767.0 | 68042.0 |
| 2253 | 2.88 | 4 | 60.0 | Кронштадт | 49488.0 | 67763.0 |
95 rows × 6 columns
Вероятно, в значении этажности положение запятой, отделяющей десятичную часть, сместилось на один знак вправо. Однако в наборе данных не представлены записи об объектах недвижимости в Кронштадте высотой 6 и даже 16 или 26 этажей.
С другой стороны, во всём наборе данных представлено большое количество объектов недвижимости, расположенных на 6 этаже, в которых высота потолков может быть не менее 2,88 м.
data[data['ceiling_height'] >= 2.88]['floors_total'].value_counts().head()
floors_total 5.0 885 4.0 444 6.0 422 7.0 224 3.0 171 Name: count, dtype: int64
Заменим 60 на 6 в обозначении этажности.
data.loc[data['floors_total'] == 60, 'floors_total'] = 6
data.loc[[2253], columns]
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 2253 | 2.88 | 4 | 6.0 | Кронштадт | 49488.0 | 67763.0 |
Запись № 16731. В наборе данных отсутствуют записи об объектах недвижимости, расположенных на таком же расстоянии от центра Санкт-Петербурга и от аэропорта. Поскольку объект расположен на 18 этаже, и высота потолков составляет 2,65 м, найдём сведения о зданиях высотой не менее 18 этажей с высотой потолков в квартирах не менее 2,65 м.
data.loc[(data['floors_total'] >= 18) &
(data['ceiling_height'] >= 2.65),
'floors_total'].value_counts().head()
floors_total 25.0 447 18.0 196 23.0 178 24.0 178 20.0 142 Name: count, dtype: int64
Наибольшее число зданий, подходящих под выбранный критерий, — это 25-этажные здания. Вероятно, была допущена ошибка при наборе значения количества этажей в здании, и цифры были записаны в обратном порядке. Заменим 52 на 25 в обозначении этажности.
data.loc[data['floors_total'] == 52, 'floors_total'] = 25
data.loc[[16731], columns]
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 16731 | 2.65 | 18 | 25.0 | Санкт-Петербург | 12978.0 | 20728.0 |
В списке уникальных значений признака floors_total можно заметить, что после значения 29 следующее значение идёт 33.
Выясним, на каких расстояниях от центра Санкт-Петербурга и аэропорта расположены здания этажностью более 29 этажей.
data.loc[data['floors_total'] >= 30,
'city_centers_nearest'].sort_values().unique()
array([20339., 20444., 20450.])
data.loc[data['floors_total'] >= 30,
'airports_nearest'].sort_values().unique()
array([18627., 18732., 18737.])
Все объекты расположены в здании, расположенном в одном месте. Значения расстояний до центра Санкт-Петербурга и до аэропорта различаются незначительно. Это может быть связано с различным способом построения маршрута на Яндекс.Картах, либо напрямую связано с разными дистанциями, преодолеваемыми до разных секций жилого комплекса.
Заменим все значения этажности, превышающие 29, на 35.
data.loc[data['floors_total'] >= 30, 'floors_total'] = 35
data['floors_total'].sort_values(ascending=False).unique()
array([35., 29., 28., 27., 26., 25., 24., 23., 22., 21., 20., 19., 18.,
17., 16., 15., 14., 13., 12., 11., 10., 9., 8., 7., 6., 5.,
4., 3., 2., 1., nan])
Этажность зданий не превышает значения 35 — этажности самого высокого жилого здания Санкт-Петербурга и Ленинградской области.
Среди всех значений признака airports_nearest одно вызывает наибольшее сомнение. Если бы значение 0 м было правильным, это бы означало, что объект недвижимости расположен в аэропорту, что, конечно же, неправда.
data['airports_nearest'].value_counts().sort_index().head()
airports_nearest 0.0 1 6450.0 2 6914.0 1 6949.0 1 6989.0 6 Name: count, dtype: int64
Обзор значений
Выясним, где на самом деле расположены объекты, расстояние от которых до аэропорта равно 0 м.
data[columns][data['airports_nearest'] == 0]
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 21085 | 2.7 | 3 | 9.0 | Санкт-Петербург | 22801.0 | 0.0 |
Такой объект один, и расположен он в Санкт-Петербурге. Вероятно, имел место технический сбой, который и привёл к потере значения.
Запись № 21085. Выясним, есть ли поблизости схожие по характеристикам здания.
data[columns][(data['city_centers_nearest'] > 22500) &
(data['city_centers_nearest'] < 23000) &
(data['floors_total'] == 9)] \
.sort_values(by='city_centers_nearest')
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 19440 | 2.55 | 1 | 9.0 | Санкт-Петербург | 22619.0 | 20907.0 |
| 21085 | 2.70 | 3 | 9.0 | Санкт-Петербург | 22801.0 | 0.0 |
| 21621 | NaN | 1 | 9.0 | Санкт-Петербург | 22902.0 | 21190.0 |
Рядом с 9-этажным зданием расположены другие 9-этажные здания (или секции этого же здания). Легко заметить, что изменение расстояний до центра Санкт-Петербурга и до аэропорта происходят симбатно и изменяются на одну и ту же величину. Тогда наиболее вероятное значение расстояния до аэропорта у объекта будет 21 100 м. Заменим 0 м на 21 100 м.
data.loc[21085, 'airports_nearest'] = 21100
data.loc[[21085], columns]
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 21085 | 2.7 | 3 | 9.0 | Санкт-Петербург | 22801.0 | 21100.0 |
data['airports_nearest'].value_counts().sort_index().head()
airports_nearest 6450.0 2 6914.0 1 6949.0 1 6989.0 6 6992.0 1 Name: count, dtype: int64
Все объекты недвижимости расположены на удалении от аэропорта. На территории аэропорта объектов жилой недвижимости нет.
Признак parks_nearest содержит экстремальные значения: превышающие 3 км.
data['parks_nearest'].value_counts().sort_index().tail()
parks_nearest 2905.0 1 2984.0 1 3013.0 1 3064.0 1 3190.0 2 Name: count, dtype: int64
Значения признака parks_around_3000 указывает на количество ближайших парков в радиусе 3 км от здания, в котором расположен объект недвижимости. Таким образом, значения признаков pakrs_around_3000 и parks_nearest являются связанными. Значения этих признаков должны быть согласованы.
Обзор значений
Выясним, какие записи содержат значение признака parks_nearest, превышающее 3000 м.
columns = ['locality_name', 'parks_around_3000', 'parks_nearest']
data[columns][data['parks_nearest'] >= 3000]
| locality_name | parks_around_3000 | parks_nearest | |
|---|---|---|---|
| 1590 | Санкт-Петербург | 0.0 | 3064.0 |
| 10959 | Санкт-Петербург | 0.0 | 3190.0 |
| 19208 | Санкт-Петербург | 0.0 | 3013.0 |
| 19430 | Санкт-Петербург | 0.0 | 3190.0 |
Таких записей всего четыре. Можно заметить, что количество парков в радиусе 3 км равно 0. Этот уровень значений признака parks_around_3000 указан в явном виде.
Редактирование значений
Вероятно, имел место технический сбой, поэтому Яндекс.Карты записали значение расстояния до ближайшего парка, несмотря на то, что оно превышает 3 км. Либо для значений признака parks_nearest установлена высокая предельно допустимая погрешность.
Заменим значения, превышающие 3000 м, на NaN. И убедимся, что все указанные расстояния до ближайшего парка не превышают 3 км.
data.loc[data['parks_nearest'] >= 3000, 'parks_nearest'] = np.nan
len(data[data['parks_nearest'] >= 3000])
0
Посмотрим на значения расстояний до ближайшего парка, близкие к граничному значению — 3 км.
columns = ['locality_name', 'city_centers_nearest',
'parks_around_3000', 'parks_nearest']
data[columns].sort_values(by='parks_nearest', ascending=False).head(10)
| locality_name | city_centers_nearest | parks_around_3000 | parks_nearest | |
|---|---|---|---|---|
| 23080 | Санкт-Петербург | 9877.0 | 1.0 | 2984.0 |
| 2659 | Санкт-Петербург | 9016.0 | 1.0 | 2905.0 |
| 1860 | Санкт-Петербург | 9983.0 | 1.0 | 2888.0 |
| 7855 | Санкт-Петербург | 9972.0 | 1.0 | 2880.0 |
| 3865 | Санкт-Петербург | 8791.0 | 1.0 | 2847.0 |
| 22003 | Санкт-Петербург | 8879.0 | 1.0 | 2768.0 |
| 7316 | Санкт-Петербург | 8679.0 | 2.0 | 2747.0 |
| 5923 | Санкт-Петербург | 8729.0 | 1.0 | 2711.0 |
| 1804 | Санкт-Петербург | 9271.0 | 2.0 | 2665.0 |
| 6625 | Санкт-Петербург | 10124.0 | 1.0 | 2633.0 |
Поскольку значение количества ближайших парков равно одному для граничных значений расстояния до ближайшего парка, можно в данном случае заключить, что значения признаков parks_around_3000 и parks_nearest не противоречат друг другу.
Если значения расстояний до ближайшего парка ограничены сверху природой признака parks_around_3000, то для ограничения снизу такого связанного признака нет. Однако значения расстояний должны отвечать здравому смыслу.
В наборе данных наблюдаются записи с подозрительно маленькими расстояниями до ближайшего парка. Маленькое расстояние до парка (порядка нескольких метров) означало бы, что выход из здания, где расположен объект недвижимости, ведёт прямо в парк. Такое расположение парка относительно здания маловероятно. Зачастую необходимо перейти через автомобильную дорогу или хотя бы через асфальтированную пешеходную дорогу, примыкающую непосредственно к зданию.
Обзор значений
Выясним, в скольких записях указано маленькое расстояние от здания до ближайшего парка и где расположены эти здания.
columns = ['floor', 'floors_total', 'locality_name', 'city_centers_nearest',
'parks_around_3000', 'parks_nearest']
data[columns][data['parks_nearest'] > 0].sort_values(by='parks_nearest').head(20)
| floor | floors_total | locality_name | city_centers_nearest | parks_around_3000 | parks_nearest | |
|---|---|---|---|---|---|---|
| 14624 | 2 | 9.0 | Санкт-Петербург | 16436.0 | 1.0 | 1.0 |
| 11949 | 7 | 9.0 | Санкт-Петербург | 12292.0 | 1.0 | 3.0 |
| 22941 | 4 | 4.0 | Зеленогорск | 54490.0 | 3.0 | 4.0 |
| 9344 | 1 | 9.0 | Санкт-Петербург | 11665.0 | 1.0 | 7.0 |
| 2527 | 2 | 5.0 | Кронштадт | 51500.0 | 3.0 | 9.0 |
| 20193 | 3 | 9.0 | Санкт-Петербург | 6410.0 | 2.0 | 9.0 |
| 15296 | 9 | 9.0 | Санкт-Петербург | 12168.0 | 1.0 | 10.0 |
| 189 | 5 | 9.0 | Санкт-Петербург | 12168.0 | 1.0 | 10.0 |
| 19093 | 2 | 9.0 | Санкт-Петербург | 12168.0 | 1.0 | 10.0 |
| 21773 | 4 | 9.0 | Санкт-Петербург | 12168.0 | 1.0 | 10.0 |
| 4470 | 3 | 9.0 | Санкт-Петербург | 12168.0 | 1.0 | 10.0 |
| 7788 | 3 | 7.0 | Санкт-Петербург | 10661.0 | 2.0 | 10.0 |
| 214 | 8 | 9.0 | Санкт-Петербург | 12168.0 | 1.0 | 10.0 |
| 12018 | 3 | 5.0 | Санкт-Петербург | 7419.0 | 2.0 | 11.0 |
| 16831 | 10 | 12.0 | Санкт-Петербург | 9555.0 | 1.0 | 11.0 |
| 21167 | 3 | 5.0 | Пушкин | 33161.0 | 1.0 | 11.0 |
| 1214 | 8 | 9.0 | Санкт-Петербург | 11564.0 | 2.0 | 11.0 |
| 19215 | 6 | 9.0 | Санкт-Петербург | 11564.0 | 2.0 | 11.0 |
| 14015 | 2 | 9.0 | Пушкин | 32456.0 | 1.0 | 12.0 |
| 22791 | 2 | 3.0 | Петергоф | 30627.0 | 2.0 | 13.0 |
Практически все объекты расположены в Санкт-Петербурге. Расстояние до ближайшего парка, равное нескольким метрам, указано в шести записях. Основная масса значений начинается с 10 м. Поэтому представляется разумным задать в качестве критерия минимальную границу значения расстояния от здания до ближайшего парка — 10 м.
Редактирование значений
В записях, в которых указано расстояние до ближайшего парка менее 10 м, заменим значения расстояний на 10 м.
data.loc[data['parks_nearest'] < 10, 'parks_nearest'] = 10
len(data[(data['parks_nearest'] < 10) & (data['parks_nearest'] > 0)])
0
data['parks_nearest'].value_counts().sort_index().head()
parks_nearest 10.0 13 11.0 5 12.0 1 13.0 6 14.0 1 Name: count, dtype: int64
data['parks_nearest'].value_counts().sort_index().tail()
parks_nearest 2847.0 1 2880.0 1 2888.0 1 2905.0 1 2984.0 1 Name: count, dtype: int64
Все значения расстояния до ближайшего парка лежат в диапазоне от 10 м до 3000 м.
Среди значений высоты потолков можно заметить экстремально большие значения — превышающие 10 м, и аномально низкие значения — не превышающие 1,5 м.
data['ceiling_height'].sort_values(ascending=False).unique()
array([32. , 27. , 26. , 25. , 24. , 22.6 , 20. , 14. , 10.3 ,
8.3 , 8. , 6. , 5.8 , 5.6 , 5.5 , 5.3 , 5.2 , 5. ,
4.9 , 4.8 , 4.7 , 4.65, 4.5 , 4.45, 4.4 , 4.37, 4.3 ,
4.25, 4.2 , 4.19, 4.15, 4.14, 4.1 , 4.06, 4. , 3.98,
3.95, 3.93, 3.9 , 3.88, 3.87, 3.86, 3.85, 3.84, 3.83,
3.82, 3.8 , 3.78, 3.76, 3.75, 3.7 , 3.69, 3.68, 3.67,
3.66, 3.65, 3.63, 3.62, 3.6 , 3.59, 3.58, 3.57, 3.56,
3.55, 3.54, 3.53, 3.52, 3.51, 3.5 , 3.49, 3.48, 3.47,
3.46, 3.45, 3.44, 3.43, 3.42, 3.4 , 3.39, 3.38, 3.37,
3.36, 3.35, 3.34, 3.33, 3.32, 3.31, 3.3 , 3.29, 3.28,
3.27, 3.26, 3.25, 3.24, 3.23, 3.22, 3.21, 3.2 , 3.18,
3.17, 3.16, 3.15, 3.14, 3.13, 3.12, 3.11, 3.1 , 3.09,
3.08, 3.07, 3.06, 3.05, 3.04, 3.03, 3.02, 3.01, 3. ,
2.99, 2.98, 2.97, 2.96, 2.95, 2.94, 2.93, 2.92, 2.91,
2.9 , 2.89, 2.88, 2.87, 2.86, 2.85, 2.84, 2.83, 2.82,
2.81, 2.8 , 2.79, 2.78, 2.77, 2.76, 2.75, 2.74, 2.73,
2.72, 2.71, 2.7 , 2.69, 2.68, 2.67, 2.66, 2.65, 2.64,
2.63, 2.62, 2.61, 2.6 , 2.59, 2.58, 2.57, 2.56, 2.55,
2.54, 2.53, 2.52, 2.51, 2.5 , 2.49, 2.48, 2.47, 2.46,
2.45, 2.4 , 2.34, 2.3 , 2.25, 2. , 1.75, 1.2 , 1. ,
nan])
Редактирование значений
Вероятно, в значениях 20—32 м положение запятой, отделяющей десятичную часть, сместилось на один знак вправо. Уменьшим эти значения в 10 раз.
data.loc[data['ceiling_height'] >= 20, 'ceiling_height'] = data['ceiling_height'] / 10
data['ceiling_height'].sort_values(ascending=False).unique()
array([14. , 10.3 , 8.3 , 8. , 6. , 5.8 , 5.6 , 5.5 , 5.3 ,
5.2 , 5. , 4.9 , 4.8 , 4.7 , 4.65, 4.5 , 4.45, 4.4 ,
4.37, 4.3 , 4.25, 4.2 , 4.19, 4.15, 4.14, 4.1 , 4.06,
4. , 3.98, 3.95, 3.93, 3.9 , 3.88, 3.87, 3.86, 3.85,
3.84, 3.83, 3.82, 3.8 , 3.78, 3.76, 3.75, 3.7 , 3.69,
3.68, 3.67, 3.66, 3.65, 3.63, 3.62, 3.6 , 3.59, 3.58,
3.57, 3.56, 3.55, 3.54, 3.53, 3.52, 3.51, 3.5 , 3.49,
3.48, 3.47, 3.46, 3.45, 3.44, 3.43, 3.42, 3.4 , 3.39,
3.38, 3.37, 3.36, 3.35, 3.34, 3.33, 3.32, 3.31, 3.3 ,
3.29, 3.28, 3.27, 3.26, 3.25, 3.24, 3.23, 3.22, 3.21,
3.2 , 3.18, 3.17, 3.16, 3.15, 3.14, 3.13, 3.12, 3.11,
3.1 , 3.09, 3.08, 3.07, 3.06, 3.05, 3.04, 3.03, 3.02,
3.01, 3. , 2.99, 2.98, 2.97, 2.96, 2.95, 2.94, 2.93,
2.92, 2.91, 2.9 , 2.89, 2.88, 2.87, 2.86, 2.85, 2.84,
2.83, 2.82, 2.81, 2.8 , 2.79, 2.78, 2.77, 2.76, 2.75,
2.74, 2.73, 2.72, 2.71, 2.7 , 2.69, 2.68, 2.67, 2.66,
2.65, 2.64, 2.63, 2.62, 2.61, 2.6 , 2.59, 2.58, 2.57,
2.56, 2.55, 2.54, 2.53, 2.52, 2.51, 2.5 , 2.49, 2.48,
2.47, 2.46, 2.45, 2.4 , 2.34, 2.3 , 2.26, 2.25, 2. ,
1.75, 1.2 , 1. , nan])
Запись № 15061. Объект недвижимости расположен на 5 этаже 14-этажного здания. Высота потолков 14 м является ошибочным значением.
columns = ['ceiling_height', 'floor', 'floors_total', 'locality_name',
'city_centers_nearest', 'airports_nearest']
data[columns][data['ceiling_height'] == 14]
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 15061 | 14.0 | 5 | 14.0 | Санкт-Петербург | 13610.0 | 14814.0 |
Найдём объекты недвижимости, расположенные поблизости и имеющие схожие характеристики.
data[columns][(data['ceiling_height'].notna()) &
(data['locality_name'] == 'Санкт-Петербург') &
(data['city_centers_nearest'] > 13600) &
(data['city_centers_nearest'] < 13620) &
(data['airports_nearest'] > 14800) &
(data['airports_nearest'] < 14830)].sort_values('ceiling_height')
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 2050 | 2.6 | 8 | 12.0 | Санкт-Петербург | 13606.0 | 14809.0 |
| 2524 | 2.7 | 1 | 12.0 | Санкт-Петербург | 13606.0 | 14809.0 |
| 8748 | 2.7 | 6 | 16.0 | Санкт-Петербург | 13606.0 | 14809.0 |
| 11610 | 2.7 | 16 | 16.0 | Санкт-Петербург | 13606.0 | 14809.0 |
| 15058 | 2.7 | 5 | 16.0 | Санкт-Петербург | 13606.0 | 14809.0 |
| 15515 | 2.7 | 13 | 16.0 | Санкт-Петербург | 13606.0 | 14809.0 |
| 16299 | 2.7 | 7 | 16.0 | Санкт-Петербург | 13606.0 | 14809.0 |
| 19243 | 2.7 | 7 | 16.0 | Санкт-Петербург | 13606.0 | 14809.0 |
| 20774 | 2.7 | 1 | 16.0 | Санкт-Петербург | 13606.0 | 14809.0 |
| 21678 | 2.7 | 8 | 10.0 | Санкт-Петербург | 13607.0 | 14811.0 |
| 22579 | 2.7 | 1 | 16.0 | Санкт-Петербург | 13606.0 | 14809.0 |
| 15061 | 14.0 | 5 | 14.0 | Санкт-Петербург | 13610.0 | 14814.0 |
Найденные объекты недвижимости преимущественно имеют высоту потолков равную 2,7 м. Заменим значение высоты потолка 14 м на 2,7 м.
data.loc[data['ceiling_height'] == 14, 'ceiling_height'] = 2.7
data.loc[[15061], columns]
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 15061 | 2.7 | 5 | 14.0 | Санкт-Петербург | 13610.0 | 14814.0 |
Запись № 22309. Объект недвижимости расположен на 15 этаже 16-этажного здания. Высота потолков 10,3 м является ошибочным значением.
data[columns][data['ceiling_height'] == 10.3]
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 22309 | 10.3 | 15 | 16.0 | Санкт-Петербург | 11936.0 | 36353.0 |
Найдём объекты недвижимости, расположенные поблизости и имеющие схожие характеристики.
data[columns][(data['ceiling_height'].notna()) &
(data['city_centers_nearest'] == 11936) &
(data['airports_nearest'] == 36353)].sort_values('ceiling_height')
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 16892 | 2.50 | 13 | 15.0 | Санкт-Петербург | 11936.0 | 36353.0 |
| 19531 | 2.75 | 2 | 16.0 | Санкт-Петербург | 11936.0 | 36353.0 |
| 1207 | 2.77 | 12 | 16.0 | Санкт-Петербург | 11936.0 | 36353.0 |
| 10772 | 2.80 | 7 | 16.0 | Санкт-Петербург | 11936.0 | 36353.0 |
| 12770 | 2.80 | 4 | 16.0 | Санкт-Петербург | 11936.0 | 36353.0 |
| 22309 | 10.30 | 15 | 16.0 | Санкт-Петербург | 11936.0 | 36353.0 |
Найденные объекты недвижимости имеют высоту потолков в интервале 2,5—2,8 м. Такой разброс значений может быть связан с уменьшением высоты потолка после установки натяжного потолка или монтажа многоуровневой потолочной системы. Заменим значение высоты потолка 10,3 м на среднее арифметическое значение — 2,7 м.
data.loc[data['ceiling_height'] == 10.3, 'ceiling_height'] = 2.7
data.loc[[22309], columns]
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 22309 | 2.7 | 15 | 16.0 | Санкт-Петербург | 11936.0 | 36353.0 |
Запись № 5863. Объект недвижимости расположен на 14 этаже 16-этажного здания. Высота потолков 8,3 м является ошибочным значением.
data[columns][data['ceiling_height'] == 8.3]
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 5863 | 8.3 | 14 | 16.0 | Санкт-Петербург | 10763.0 | 13069.0 |
Поскольку не представляется возможным найти похожие по характеристикам объекты недвижимости, узнаем медианное значение высоты потолков 16-этажных зданий, расположенных в Санкт-Петербурге.
data[columns][(data['ceiling_height'].notna()) &
(data['locality_name'] == 'Санкт-Петербург') &
(data['floors_total'] == 16)]['ceiling_height'].median()
2.7
Медианное значение составляет 2,7 м. Заменим значение высоты потолка 8,3 м на 2,7 м.
data.loc[data['ceiling_height'] == 8.3, 'ceiling_height'] = 2.7
data.loc[[5863], columns]
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 5863 | 2.7 | 14 | 16.0 | Санкт-Петербург | 10763.0 | 13069.0 |
Высота потолков равная 8 м указана сразу в трёх записях. Все объекты недвижимости расположены в разных населённых пунктах на 1 или 2 этажах зданий.
data[columns][data['ceiling_height'] == 8]
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 3474 | 8.0 | 2 | 5.0 | Нурма | NaN | NaN |
| 15743 | 8.0 | 1 | 16.0 | Санкт-Петербург | 11035.0 | 32691.0 |
| 17442 | 8.0 | 2 | 5.0 | Красное Село | 28062.0 | 24638.0 |
Запись № 15743. Объект недвижимости расположен на 1 этаже 16-этажного здания в Санкт-Петербурге. Найдём похожие по характеристикам объекты недвижимости.
data[columns][(data['ceiling_height'].notna()) &
(data['city_centers_nearest'] == 11035) &
(data['airports_nearest'] == 32691)].sort_values('ceiling_height')
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 22271 | 2.5 | 4 | 15.0 | Санкт-Петербург | 11035.0 | 32691.0 |
| 15743 | 8.0 | 1 | 16.0 | Санкт-Петербург | 11035.0 | 32691.0 |
Схожий по характеристикам объект недвижимости имеет высоту потолков 2,5 м. Заменим значение высоты потолка 8 м на 2,5 м.
data.loc[15743, 'ceiling_height'] = 2.5
data.loc[[15743], columns]
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 15743 | 2.5 | 1 | 16.0 | Санкт-Петербург | 11035.0 | 32691.0 |
Запись № 17442. Объект недвижимости расположен на 2 этаже 5-этажного здания в Красном Селе. Найдём похожие по характеристикам объекты недвижимости.
data[columns][(data['ceiling_height'].notna()) &
(data['city_centers_nearest'] == 28062) &
(data['airports_nearest'] == 24638)].sort_values('ceiling_height')
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 10392 | 2.75 | 3 | 5.0 | Красное Село | 28062.0 | 24638.0 |
| 17442 | 8.00 | 2 | 5.0 | Красное Село | 28062.0 | 24638.0 |
Схожий по характеристикам объект недвижимости имеет высоту потолков 2,75 м. Заменим значение высоты потолка 8 м на 2,75 м.
data.loc[17442, 'ceiling_height'] = 2.75
data.loc[[17442], columns]
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 17442 | 2.75 | 2 | 5.0 | Красное Село | 28062.0 | 24638.0 |
Запись № 3474. Объект недвижимости расположен на 2 этаже 5-этажного здания в Нурме. Найдём похожие по характеристикам объекты недвижимости.
data[columns][(data['ceiling_height'].notna()) &
(data['locality_name'] == 'Нурма') &
(data['floors_total'] == 5)].sort_values('ceiling_height')
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 596 | 2.5 | 3 | 5.0 | Нурма | NaN | NaN |
| 1570 | 2.5 | 5 | 5.0 | Нурма | NaN | NaN |
| 3917 | 2.5 | 5 | 5.0 | Нурма | NaN | NaN |
| 4599 | 2.5 | 5 | 5.0 | Нурма | NaN | NaN |
| 11842 | 2.5 | 5 | 5.0 | Нурма | NaN | NaN |
| 21376 | 2.5 | 4 | 5.0 | Нурма | NaN | NaN |
| 18916 | 2.6 | 1 | 5.0 | Нурма | NaN | NaN |
| 3474 | 8.0 | 2 | 5.0 | Нурма | NaN | NaN |
Схожие по характеристикам объекты недвижимости имеют высоту потолков 2,5 м. Заменим значение высоты потолка 8 м на 2,5 м.
data.loc[3474, 'ceiling_height'] = 2.5
data.loc[[3474], columns]
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 3474 | 2.5 | 2 | 5.0 | Нурма | NaN | NaN |
data[columns].sort_values(by='ceiling_height', ascending=False).head(10)
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 20264 | 6.0 | 7 | 7.0 | Санкт-Петербург | 5605.0 | 26902.0 |
| 21227 | 5.8 | 5 | 5.0 | Санкт-Петербург | 1261.0 | 20170.0 |
| 1388 | 5.6 | 6 | 6.0 | Санкт-Петербург | 6934.0 | 26204.0 |
| 7578 | 5.5 | 5 | 5.0 | Санкт-Петербург | 6448.0 | 26333.0 |
| 1026 | 5.3 | 3 | 3.0 | Санкт-Петербург | 4785.0 | 24899.0 |
| 12628 | 5.3 | 5 | 5.0 | Санкт-Петербург | 3918.0 | 19644.0 |
| 464 | 5.2 | 7 | 8.0 | Санкт-Петербург | 6655.0 | 26316.0 |
| 1053 | 5.0 | 1 | 3.0 | Бокситогорск | NaN | NaN |
| 21923 | 4.9 | 5 | 5.0 | Санкт-Петербург | 1328.0 | 22777.0 |
| 2802 | 4.8 | 2 | 3.0 | Санкт-Петербург | 1725.0 | 24433.0 |
Значение высоты потолка равное 6 м и менее является допустимым, поскольку объекты недвижимости с высокими потолками располагаются на последних этажах зданий и зачастую имеют большую площадь. Это позволяет предполагать, что данные объекты недвижимости являются пентхаусом.
Поскольку в определении этажа есть указание, что это "пространство высотой в чистоте (от пола до потолка) 1,8 м и более", и если ещё учитывать средний рост человека, то логично предположить, что значения высоты потолков менее 1,8 м является также ошибочными.
Запись № 22590. Объект недвижимости расположен на 7 этаже 12-этажного здания. Значение высоты потолков 1 м является ошибочным.
data[columns][data['ceiling_height'] == 1]
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 22590 | 1.0 | 7 | 12.0 | Санкт-Петербург | 14217.0 | 33053.0 |
Найдём схожие по характеристикам объекты недвижимости.
data[columns][(data['ceiling_height'].notna()) &
(data['city_centers_nearest'] == 14217) &
(data['airports_nearest'] == 33053)]
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 15420 | 2.7 | 2 | 12.0 | Санкт-Петербург | 14217.0 | 33053.0 |
| 22590 | 1.0 | 7 | 12.0 | Санкт-Петербург | 14217.0 | 33053.0 |
Схожий объект недвижимости имеет высоту потолка 2,7 м. Заменим значение высоты потолка 1 м на 2,7 м.
data.loc[22590, 'ceiling_height'] = 2.7
data.loc[[22590], columns]
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 22590 | 2.7 | 7 | 12.0 | Санкт-Петербург | 14217.0 | 33053.0 |
Запись № 5172. Объект недвижимости расположен на 1 этаже 2-этажного здания. Значение высоты потолков 1,2 м является ошибочным.
data[columns][data['ceiling_height'] == 1.2]
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 5712 | 1.2 | 1 | 2.0 | Мга | NaN | NaN |
Найдём схожие по характеристикам объекты недвижимости.
data[columns][(data['ceiling_height'].notna()) &
(data['locality_name'] == 'Мга') &
(data['floors_total'] == 2)]
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 5712 | 1.2 | 1 | 2.0 | Мга | NaN | NaN |
| 6148 | 2.5 | 1 | 2.0 | Мга | NaN | NaN |
| 7733 | 2.6 | 2 | 2.0 | Мга | NaN | NaN |
| 18636 | 3.2 | 2 | 2.0 | Мга | NaN | NaN |
| 18858 | 2.6 | 2 | 2.0 | Мга | NaN | NaN |
Схожими по характеристикам являются несколько объектов недвижимости. Значение высоты потолков у них находится в диапазоне 2,5—3,2 м. Медианное значение равно 2,6 м. Заменим значение высоты потолка 1,2 м на медианное значение 2,6 м.
data.loc[5712, 'ceiling_height'] = 2.6
data.loc[[5712], columns]
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 5712 | 2.6 | 1 | 2.0 | Мга | NaN | NaN |
Запись № 16934. Объект недвижимости расположен на 5 этаже 35-этажного здания жилого комплекса "Князь Александр Невский". И хотя значение высоты потолка 1,75 м является близким по значению к 1,8 м, всё же для квартиры в новостройке оно представляется сомнительным.
data[columns][data['ceiling_height'] == 1.75]
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 16934 | 1.75 | 5 | 35.0 | Санкт-Петербург | 20444.0 | 18732.0 |
Выясним, какой высоты потолки в ЖК "Князь Александр Невский".
data[columns][data['ceiling_height'].notna() &
(data['floors_total'] == 35)]
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 1697 | 2.65 | 23 | 35.0 | Санкт-Петербург | 20444.0 | 18732.0 |
| 1917 | 2.80 | 30 | 35.0 | Санкт-Петербург | 20444.0 | 18732.0 |
| 4855 | 2.80 | 4 | 35.0 | Санкт-Петербург | 20339.0 | 18627.0 |
| 5749 | 2.80 | 26 | 35.0 | Санкт-Петербург | 20444.0 | 18732.0 |
| 5807 | 2.70 | 13 | 35.0 | Санкт-Петербург | 20444.0 | 18732.0 |
| 9186 | 2.50 | 3 | 35.0 | Санкт-Петербург | 20444.0 | 18732.0 |
| 9370 | 2.70 | 3 | 35.0 | Санкт-Петербург | 20444.0 | 18732.0 |
| 9579 | 2.68 | 17 | 35.0 | Санкт-Петербург | 20444.0 | 18732.0 |
| 11079 | 2.70 | 29 | 35.0 | Санкт-Петербург | 20444.0 | 18732.0 |
| 12888 | 2.70 | 27 | 35.0 | Санкт-Петербург | 20444.0 | 18732.0 |
| 12960 | 2.70 | 13 | 35.0 | Санкт-Петербург | 20444.0 | 18732.0 |
| 16934 | 1.75 | 5 | 35.0 | Санкт-Петербург | 20444.0 | 18732.0 |
data[data['floors_total'] == 35]['ceiling_height'].median()
2.7
Высота потолков в ЖК "Князь Александр Невский" изменяется в диапазоне 2,5—2,8 м. Медианное значение — 2,7 м. Однако, вероятнее всего, была допущена ошибка при вводе значения высоты потолка: вместо цифры 2 была указана цифра 1. Поэтому заменим значение высоты потолка 1,75 м на 2,75 м.
data.loc[data['ceiling_height'] == 1.75, 'ceiling_height'] = 2.75
data.loc[[16934], columns]
| ceiling_height | floor | floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|---|---|
| 16934 | 2.75 | 5 | 35.0 | Санкт-Петербург | 20444.0 | 18732.0 |
data['ceiling_height'].sort_values(ascending=False).unique()
array([6. , 5.8 , 5.6 , 5.5 , 5.3 , 5.2 , 5. , 4.9 , 4.8 , 4.7 , 4.65,
4.5 , 4.45, 4.4 , 4.37, 4.3 , 4.25, 4.2 , 4.19, 4.15, 4.14, 4.1 ,
4.06, 4. , 3.98, 3.95, 3.93, 3.9 , 3.88, 3.87, 3.86, 3.85, 3.84,
3.83, 3.82, 3.8 , 3.78, 3.76, 3.75, 3.7 , 3.69, 3.68, 3.67, 3.66,
3.65, 3.63, 3.62, 3.6 , 3.59, 3.58, 3.57, 3.56, 3.55, 3.54, 3.53,
3.52, 3.51, 3.5 , 3.49, 3.48, 3.47, 3.46, 3.45, 3.44, 3.43, 3.42,
3.4 , 3.39, 3.38, 3.37, 3.36, 3.35, 3.34, 3.33, 3.32, 3.31, 3.3 ,
3.29, 3.28, 3.27, 3.26, 3.25, 3.24, 3.23, 3.22, 3.21, 3.2 , 3.18,
3.17, 3.16, 3.15, 3.14, 3.13, 3.12, 3.11, 3.1 , 3.09, 3.08, 3.07,
3.06, 3.05, 3.04, 3.03, 3.02, 3.01, 3. , 2.99, 2.98, 2.97, 2.96,
2.95, 2.94, 2.93, 2.92, 2.91, 2.9 , 2.89, 2.88, 2.87, 2.86, 2.85,
2.84, 2.83, 2.82, 2.81, 2.8 , 2.79, 2.78, 2.77, 2.76, 2.75, 2.74,
2.73, 2.72, 2.71, 2.7 , 2.69, 2.68, 2.67, 2.66, 2.65, 2.64, 2.63,
2.62, 2.61, 2.6 , 2.59, 2.58, 2.57, 2.56, 2.55, 2.54, 2.53, 2.52,
2.51, 2.5 , 2.49, 2.48, 2.47, 2.46, 2.45, 2.4 , 2.34, 2.3 , 2.26,
2.25, 2. , nan])
Значения высоты потолков во всех объектах недвижимости находятся в диапазоне 2—6 м.
Признак rooms измеряется в порядковой шкале. Значения признака — это уровни, характеризующие объект недвижимости и напрямую связанные с количеством имеющихся жилых комнат (размеченных на плане помещения, либо физически разграниченных стенами внутри помещения). Шкала состоит из ряда натуральных чисел. Шкала не имеет значения ноль, поскольку это значение физически не достижимо (в жилом помещении должна быть хотя бы одна жилая комната).
data['rooms'].sort_values().unique()
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 19],
dtype=int64)
Ноль в значении признака rooms может быть меткой того, что объектом недвижимости является квартира-студия.
data[data['studio']]['rooms'].value_counts()
rooms 0 138 1 11 Name: count, dtype: int64
Действительно, из 149 записей, в которых отмечено, что объект недвижимости является квартирой-студией, в 138 указано, что количество комнат равно нулю. Однако в 11 записях указано количество комнат равное одному. В законе нет понятия "квартира-студия", поэтому все квартиры-студии должны иметь, по крайней мере, одну жилую комнату. С этой точки зрения, 11 записей были сделаны верно.
data[data['studio'] & (data['rooms'] == 1)]['total_area'].sort_values().unique()
array([22. , 23.4 , 25.41, 26. , 27. , 28. , 30. , 31. , 32.5 ,
34. ])
Зачастую квартирами-студиями называют небольшие по площади однокомнатные квартиры, в которых под кухню выделена зона внутри жилого помещения. Так, общая площадь объектов недвижимости в 11 записях варьируется в диапазоне 22—34 м².
data[data['studio'] & (data['rooms'] == 0)]['total_area'].sort_values().unique()
array([15.5 , 17. , 18. , 18.8 , 19. , 19.5 , 20. , 20.5 , 21. ,
21.3 , 21.4 , 22. , 22.2 , 22.3 , 22.7 , 23. , 23.3 , 23.39,
23.4 , 23.5 , 23.6 , 23.7 , 23.8 , 24. , 24.05, 24.1 , 24.2 ,
24.4 , 24.5 , 24.6 , 24.75, 24.8 , 24.9 , 25. , 25.3 , 25.4 ,
25.7 , 26. , 26.05, 26.23, 26.49, 26.7 , 26.8 , 27. , 27.11,
27.3 , 27.4 , 27.55, 27.56, 27.6 , 27.7 , 27.81, 28. , 28.16,
28.2 , 28.4 , 28.9 , 29. , 29.1 , 29.2 , 29.3 , 30. , 30.1 ,
30.3 , 31. , 32. , 32.03, 32.2 , 32.4 , 32.5 , 32.8 , 38.3 ,
42.1 , 43.3 , 44.2 , 58.4 , 71. , 73.6 , 98.4 ])
В большинстве из 138 записей общая площадь помещения не превышает 40 м². Это даёт основание полагать, что указанные в записях объекты недвижимости — 1-комнатные квартиры с планировкой квартиры-студии.
data[data['open_plan']]['rooms'].value_counts()
rooms 0 56 1 3 3 2 2 1 5 1 4 1 Name: count, dtype: int64
Среди 67 объектов недвижимости со свободной планировкой для 59 указано количество комнат равное нулю. Это позволяет предполагать, что эти объекты недвижимости тоже являются квартирами-студиями.
В понятиях "квартира-студия" и "свободная планировка" заложен один смысл — это отсутствие в помещении разграничивающих комнаты перегородок. По смыслу, понятия являются синонимами. Таким образом, для помещения без внутренних перегородок можно указывать количество комнат, равное одному, поскольку вся жилая площадь представляет собой одну жилую комнату, либо указывать несколько комнат в соответствии с планом помещения.
data[data['open_plan']]['studio'].value_counts()
studio False 64 Name: count, dtype: int64
data[data['studio']]['open_plan'].value_counts()
open_plan False 149 Name: count, dtype: int64
И хотя ни для одного объекта недвижимости со свободной планировкой не указано, что он является квартирой-студией, и ни для одной квартиры-студии не указано, что это помещение со свободной планировкой, по сути, это понятия одной природы. Возможно, это следствие правила Яндекс.Недвижимости, что при указании одного признака другой не указывается. По факту, значения признаков должны дублировать друг друга. Кроме того, отсутствие законодательных норм в отношении данных понятий не позволяет говорить об их отличии друг от друга.
Редактирование значений
Обратим внимание, что общая площадь 1-комнатных квартир со свободной планировкой не превышает 45 м².
columns = ['total_area', 'rooms', 'floor', 'floors_total',
'studio', 'open_plan', 'locality_name']
data[columns][data['open_plan'] & (data['rooms'] == 1)]
| total_area | rooms | floor | floors_total | studio | open_plan | locality_name | |
|---|---|---|---|---|---|---|---|
| 1379 | 44.2 | 1 | 23 | 25.0 | False | True | Санкт-Петербург |
| 5668 | 36.7 | 1 | 2 | 16.0 | False | True | Кудрово |
| 9063 | 39.0 | 1 | 1 | 17.0 | False | True | Санкт-Петербург |
Тогда будем считать, что все квартиры-студии с общей площадью менее 45 м², для которых указано количество комнат равное нулю, являются однокомнатными.
data.loc[data['studio'] &
(data['rooms'] == 0) &
(data['total_area'] < 45), 'rooms'] = 1
data[data['studio'] & (data['rooms'] == 1)]['total_area'].sort_values().unique()
array([15.5 , 17. , 18. , 18.8 , 19. , 19.5 , 20. , 20.5 , 21. ,
21.3 , 21.4 , 22. , 22.2 , 22.3 , 22.7 , 23. , 23.3 , 23.39,
23.4 , 23.5 , 23.6 , 23.7 , 23.8 , 24. , 24.05, 24.1 , 24.2 ,
24.4 , 24.5 , 24.6 , 24.75, 24.8 , 24.9 , 25. , 25.3 , 25.4 ,
25.41, 25.7 , 26. , 26.05, 26.23, 26.49, 26.7 , 26.8 , 27. ,
27.11, 27.3 , 27.4 , 27.55, 27.56, 27.6 , 27.7 , 27.81, 28. ,
28.16, 28.2 , 28.4 , 28.9 , 29. , 29.1 , 29.2 , 29.3 , 30. ,
30.1 , 30.3 , 31. , 32. , 32.03, 32.2 , 32.4 , 32.5 , 32.8 ,
34. , 38.3 , 42.1 , 43.3 , 44.2 ])
Кроме того, будем считать, что все квартиры со свободной планировкой, у которых общая площадь менее 45 м², для которых указано количество комнат равное нулю, также являются однокомнатными.
data.loc[data['open_plan'] &
(data['rooms'] == 0) &
(data['total_area'] < 45), 'rooms'] = 1
data[data['open_plan'] & (data['rooms'] == 1)]['total_area'].sort_values().unique()
array([16. , 20. , 21. , 22. , 22.5 , 23. , 23.06, 23.98, 24. ,
25. , 25.2 , 25.41, 25.9 , 26. , 26.1 , 26.8 , 27. , 27.1 ,
27.3 , 27.32, 27.5 , 27.7 , 28. , 28.01, 28.05, 28.2 , 28.3 ,
28.5 , 29. , 30. , 30.5 , 31. , 31.1 , 32.3 , 34. , 34.4 ,
35. , 36.7 , 39. , 42.63, 44.2 ])
Изучим, для квартир-студий с какой общей площадью указано количество комнат равное нулю.
data[data['studio'] & (data['rooms'] == 0)]
| total_images | last_price | total_area | first_day_exposition | rooms | ceiling_height | floors_total | living_area | floor | is_apartment | studio | open_plan | kitchen_area | balcony | locality_name | airports_nearest | city_centers_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | days_exposition | locality_type | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 3458 | 6 | 7400000.0 | 73.6 | 2017-05-18T00:00:00 | 0 | NaN | 3.0 | 50.0 | 1 | NaN | True | False | NaN | 0.0 | Санкт-Петербург | 26581.0 | 6085.0 | 0.0 | NaN | 1.0 | 348.0 | 60.0 | город |
| 13613 | 16 | 8100000.0 | 58.4 | 2019-04-26T00:00:00 | 0 | 3.3 | 7.0 | 33.0 | 6 | NaN | True | False | NaN | NaN | Санкт-Петербург | 14509.0 | 8288.0 | 0.0 | NaN | 0.0 | NaN | NaN | город |
| 20082 | 10 | 16300000.0 | 98.4 | 2017-11-08T00:00:00 | 0 | 3.1 | 5.0 | 60.5 | 2 | NaN | True | False | NaN | NaN | Санкт-Петербург | 26972.0 | 5819.0 | 0.0 | NaN | 1.0 | 674.0 | 537.0 | город |
| 21227 | 0 | 8200000.0 | 71.0 | 2017-07-21T00:00:00 | 0 | 5.8 | 5.0 | 68.0 | 5 | NaN | True | False | NaN | 0.0 | Санкт-Петербург | 20170.0 | 1261.0 | 2.0 | 295.0 | 3.0 | 366.0 | 30.0 | город |
Изучим объекты со свободной планировкой и общим количеством комнат больше 1.
data[data['open_plan'] &
(data['rooms'] > 1)].sort_values(by=['rooms', 'total_area'])
| total_images | last_price | total_area | first_day_exposition | rooms | ceiling_height | floors_total | living_area | floor | is_apartment | studio | open_plan | kitchen_area | balcony | locality_name | airports_nearest | city_centers_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | days_exposition | locality_type | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 12760 | 0 | 3350000.0 | 51.0 | 2015-01-22T00:00:00 | 2 | 2.50 | 12.0 | 30.0 | 10 | NaN | False | True | NaN | 2.0 | Коммунар | NaN | NaN | NaN | NaN | NaN | NaN | 521.0 | город |
| 14017 | 13 | 3990000.0 | 59.0 | 2016-03-29T00:00:00 | 3 | 2.50 | 9.0 | 37.6 | 3 | False | False | True | NaN | 1.0 | Колпино | 27820.0 | 33606.0 | 0.0 | NaN | 1.0 | 705.0 | 81.0 | город |
| 8861 | 13 | 5500000.0 | 64.5 | 2015-11-13T00:00:00 | 3 | 3.00 | 5.0 | 48.0 | 2 | False | False | True | NaN | 0.0 | Санкт-Петербург | 20040.0 | 2621.0 | 2.0 | 205.0 | 2.0 | 204.0 | 229.0 | город |
| 19796 | 1 | 12000000.0 | 97.2 | 2016-04-05T00:00:00 | 4 | 3.35 | 5.0 | 71.3 | 2 | False | False | True | NaN | 0.0 | Санкт-Петербург | 24559.0 | 4811.0 | 0.0 | NaN | 0.0 | NaN | 89.0 | город |
| 17783 | 3 | 48763000.0 | 157.0 | 2016-04-01T00:00:00 | 5 | NaN | 11.0 | NaN | 5 | NaN | False | True | NaN | 0.0 | Санкт-Петербург | 28399.0 | 7101.0 | 2.0 | 290.0 | 3.0 | 221.0 | 90.0 | город |
Среди объектов недвижимости со свободной планировкой есть объекты 2-комнатные — с общей площадью менее 59 м², 3-комнатные — с общей площадью менее 97 м², 4-комнатные — с общей площадью менее 157 м². Следуя этому соотношению между общей площадью и количеством комнат, исправим все нулевые значения признака rooms в записях, относящихся к квартирам-студиям.
data.loc[data['studio'] & (data['rooms'] == 0) &
(data['total_area'] < 59), 'rooms'] = 2
data.loc[data['studio'] & (data['rooms'] == 0) &
(data['total_area'] < 97), 'rooms'] = 3
data.loc[data['studio'] & (data['rooms'] == 0) &
(data['total_area'] < 157), 'rooms'] = 4
data[data['studio']]['rooms'].value_counts()
rooms 1 145 3 2 2 1 4 1 Name: count, dtype: int64
Изучим, для квартир со свободной планировкой с какой общей площадью указано количество комнат равное нулю.
data[data['open_plan'] & (data['rooms'] == 0)]
| total_images | last_price | total_area | first_day_exposition | rooms | ceiling_height | floors_total | living_area | floor | is_apartment | studio | open_plan | kitchen_area | balcony | locality_name | airports_nearest | city_centers_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | days_exposition | locality_type | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 19392 | 5 | 71000000.0 | 371.0 | 2018-07-26T00:00:00 | 0 | 3.57 | 7.0 | NaN | 6 | NaN | False | True | NaN | NaN | Санкт-Петербург | 25257.0 | 6060.0 | 1.0 | 761.0 | 1.0 | 584.0 | 90.0 | город |
Среди всех объектов недвижимости, представленных в наборе данных, объекты недвижимости с такой же общей площадью имеют преимущественно 7 комнат.
data[(data['total_area'] > 360) &
(data['total_area'] < 380)]['rooms'].value_counts()
rooms 7 4 14 1 3 1 19 1 0 1 5 1 8 1 Name: count, dtype: int64
Заменим нулевое значение признака rooms в записях, относящихся к квартирам со свободной планировкой.
data.loc[data['open_plan'] & (data['rooms'] == 0), 'rooms'] = 7
data[data['open_plan']]['rooms'].value_counts()
rooms 1 58 3 2 2 1 5 1 7 1 4 1 Name: count, dtype: int64
data['rooms'].sort_values().unique()
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 19],
dtype=int64)
Продублируем значения True в признаках studio и open_plan.
data.loc[data['studio'], 'open_plan'] = True
data.loc[data['open_plan'], 'studio'] = True
(data['studio'] != data['open_plan']).sum()
0
Все значения признаков studio и open_plan совпадают. Признак rooms не содержит нулевых значений.
def show_na():
'''
Функция подсчёта пропущенных значений.
Возвращает таблицу распределения пропущенных значений,
отсортированную по убыванию значений.
'''
total = data.isna().sum().sort_values(ascending=False)
percent = (data.isna().sum() /
data.isna().count() * 100).round(1).sort_values(ascending=False)
display(pd.concat([total, percent], axis=1, keys=['Всего пропусков', '%']))
show_na()
| Всего пропусков | % | |
|---|---|---|
| is_apartment | 20740 | 88.3 |
| parks_nearest | 15463 | 65.9 |
| ponds_nearest | 14435 | 61.5 |
| balcony | 11413 | 48.6 |
| ceiling_height | 9107 | 38.8 |
| airports_nearest | 5463 | 23.3 |
| city_centers_nearest | 5440 | 23.2 |
| ponds_around_3000 | 5439 | 23.2 |
| parks_around_3000 | 5439 | 23.2 |
| days_exposition | 3155 | 13.4 |
| kitchen_area | 2263 | 9.6 |
| living_area | 1903 | 8.1 |
| floors_total | 86 | 0.4 |
| locality_type | 49 | 0.2 |
| locality_name | 49 | 0.2 |
| total_images | 0 | 0.0 |
| last_price | 0 | 0.0 |
| studio | 0 | 0.0 |
| floor | 0 | 0.0 |
| rooms | 0 | 0.0 |
| first_day_exposition | 0 | 0.0 |
| total_area | 0 | 0.0 |
| open_plan | 0 | 0.0 |
Признак is_apartment измеряется в бинарной шкале и может иметь всего два значения: False и True. В наборе данных этот признак содержит наибольшее число пропусков.
data['is_apartment'].unique()
array([nan, False, True], dtype=object)
Относится ли квартира к апартаментам — вопрос юридический. В апартаментах нельзя оформить постоянную регистрацию и за них нельзя получить налоговый вычет. Эти факты могут оказать влияние на выбор покупателей. Поэтому разумно полагать, что для всех апартаментов в объявлении было указано об их статусе в явном виде. Следовательно, если информация об апартаментах отсутствует, значит, объект недвижимости не является апартаментами.
Заменим все отсутствующие значения на значение False.
data['is_apartment'] = data['is_apartment'].fillna(False)
data['is_apartment'].unique()
array([False, True])
show_na()
| Всего пропусков | % | |
|---|---|---|
| parks_nearest | 15463 | 65.9 |
| ponds_nearest | 14435 | 61.5 |
| balcony | 11413 | 48.6 |
| ceiling_height | 9107 | 38.8 |
| airports_nearest | 5463 | 23.3 |
| city_centers_nearest | 5440 | 23.2 |
| ponds_around_3000 | 5439 | 23.2 |
| parks_around_3000 | 5439 | 23.2 |
| days_exposition | 3155 | 13.4 |
| kitchen_area | 2263 | 9.6 |
| living_area | 1903 | 8.1 |
| floors_total | 86 | 0.4 |
| locality_type | 49 | 0.2 |
| locality_name | 49 | 0.2 |
| total_images | 0 | 0.0 |
| last_price | 0 | 0.0 |
| studio | 0 | 0.0 |
| is_apartment | 0 | 0.0 |
| floor | 0 | 0.0 |
| rooms | 0 | 0.0 |
| first_day_exposition | 0 | 0.0 |
| total_area | 0 | 0.0 |
| open_plan | 0 | 0.0 |
Признак balcony измеряется в порядковой шкале. Значения шкалы представляют собой ряд натуральных чисел. Значение ноль является меткой того, что у объекта недвижимости нет балконов. Среди всех записей почти в половине из них отсутствуют сведения о наличии балконов.
data['balcony'].sort_values().unique()
array([ 0., 1., 2., 3., 4., 5., nan])
Можно предположить, что отсутствие в объявлении о продаже объекта недвижимости сведений о количестве балконов является следствием отсутствия балконов у объекта недвижимости.
Заменим все отсутствующие значения на значение 0.
data['balcony'] = data['balcony'].fillna(0)
data['balcony'].sort_values().unique()
array([0., 1., 2., 3., 4., 5.])
show_na()
| Всего пропусков | % | |
|---|---|---|
| parks_nearest | 15463 | 65.9 |
| ponds_nearest | 14435 | 61.5 |
| ceiling_height | 9107 | 38.8 |
| airports_nearest | 5463 | 23.3 |
| city_centers_nearest | 5440 | 23.2 |
| ponds_around_3000 | 5439 | 23.2 |
| parks_around_3000 | 5439 | 23.2 |
| days_exposition | 3155 | 13.4 |
| kitchen_area | 2263 | 9.6 |
| living_area | 1903 | 8.1 |
| floors_total | 86 | 0.4 |
| locality_type | 49 | 0.2 |
| locality_name | 49 | 0.2 |
| total_images | 0 | 0.0 |
| balcony | 0 | 0.0 |
| last_price | 0 | 0.0 |
| studio | 0 | 0.0 |
| is_apartment | 0 | 0.0 |
| floor | 0 | 0.0 |
| rooms | 0 | 0.0 |
| first_day_exposition | 0 | 0.0 |
| total_area | 0 | 0.0 |
| open_plan | 0 | 0.0 |
Название населённого пункта не указано для 49 записей.
Изучим записи с отсутствующими названиями населённых пунктов, у которых есть иные картографические данные. Определим местоположение объектов по величине расстояния до центра Санкт-Петербурга, расстояния до аэропорта, а также по количеству расположенных в пределах 3 км парков и водоёмов.
columns = ['floors_total', 'locality_name', 'city_centers_nearest',
'airports_nearest', 'parks_around_3000', 'ponds_around_3000']
data[columns][data['locality_name'].isna() &
data['city_centers_nearest'].notna()] \
.sort_values('city_centers_nearest')
| floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | ponds_around_3000 | |
|---|---|---|---|---|---|---|
| 16610 | 5.0 | NaN | 1322.0 | 21219.0 | 1.0 | 3.0 |
| 22474 | 6.0 | NaN | 1780.0 | 23297.0 | 3.0 | 3.0 |
| 4189 | 4.0 | NaN | 3039.0 | 21774.0 | 1.0 | 1.0 |
| 19045 | 5.0 | NaN | 3312.0 | 21654.0 | 1.0 | 1.0 |
| 9821 | 2.0 | NaN | 3801.0 | 24953.0 | 1.0 | 2.0 |
| 4151 | 8.0 | NaN | 3902.0 | 25054.0 | 1.0 | 3.0 |
| 8568 | 6.0 | NaN | 4065.0 | 24233.0 | 1.0 | 0.0 |
| 11248 | 8.0 | NaN | 4069.0 | 25221.0 | 0.0 | 2.0 |
| 1097 | 5.0 | NaN | 4258.0 | 23478.0 | 0.0 | 0.0 |
| 20057 | 5.0 | NaN | 4258.0 | 23478.0 | 0.0 | 0.0 |
| 12936 | 5.0 | NaN | 4383.0 | 25680.0 | 3.0 | 0.0 |
| 10122 | 5.0 | NaN | 4474.0 | 25771.0 | 2.0 | 0.0 |
| 20654 | 5.0 | NaN | 4604.0 | 24385.0 | 1.0 | 0.0 |
| 7330 | 5.0 | NaN | 4627.0 | 25925.0 | 2.0 | 0.0 |
| 21333 | 6.0 | NaN | 4805.0 | 26090.0 | 0.0 | 1.0 |
| 4670 | 7.0 | NaN | 5382.0 | 26534.0 | 1.0 | 1.0 |
| 3574 | 5.0 | NaN | 8127.0 | 27419.0 | 0.0 | 1.0 |
| 18917 | 4.0 | NaN | 8429.0 | 21540.0 | 0.0 | 3.0 |
| 7114 | 5.0 | NaN | 8582.0 | 14031.0 | 0.0 | 0.0 |
| 16561 | 4.0 | NaN | 8619.0 | 21731.0 | 0.0 | 3.0 |
| 18526 | 7.0 | NaN | 8943.0 | 11206.0 | 0.0 | 0.0 |
| 23214 | 6.0 | NaN | 8943.0 | 11206.0 | 0.0 | 0.0 |
| 15866 | 5.0 | NaN | 9497.0 | 36380.0 | 1.0 | 3.0 |
| 5343 | 7.0 | NaN | 9538.0 | 10556.0 | 1.0 | 0.0 |
| 15686 | 5.0 | NaN | 9633.0 | 35920.0 | 2.0 | 3.0 |
| 17764 | 23.0 | NaN | 10976.0 | 36865.0 | 0.0 | 1.0 |
| 12879 | 12.0 | NaN | 12332.0 | 37123.0 | 0.0 | 0.0 |
| 7600 | 11.0 | NaN | 12332.0 | 37123.0 | 0.0 | 0.0 |
| 5707 | 24.0 | NaN | 16788.0 | 21460.0 | 0.0 | 1.0 |
| 14273 | 23.0 | NaN | 17369.0 | 22041.0 | 0.0 | 1.0 |
| 2603 | 24.0 | NaN | 17369.0 | 22041.0 | 0.0 | 1.0 |
| 2632 | 24.0 | NaN | 17369.0 | 22041.0 | 0.0 | 1.0 |
| 6765 | 24.0 | NaN | 17369.0 | 22041.0 | 0.0 | 1.0 |
| 22933 | 23.0 | NaN | 17369.0 | 22041.0 | 0.0 | 1.0 |
| 16499 | 24.0 | NaN | 17369.0 | 22041.0 | 0.0 | 1.0 |
| 19972 | 24.0 | NaN | 17369.0 | 22041.0 | 0.0 | 1.0 |
| 13223 | 24.0 | NaN | 17369.0 | 22041.0 | 0.0 | 1.0 |
| 13690 | 2.0 | NaN | 23659.0 | 20234.0 | 0.0 | 2.0 |
| 8986 | NaN | NaN | 31813.0 | 19659.0 | 0.0 | 0.0 |
| 21119 | 4.0 | NaN | 31897.0 | 19744.0 | 0.0 | 0.0 |
| 21276 | 3.0 | NaN | 41294.0 | 60195.0 | 0.0 | 0.0 |
Расстояние от всех объектов недвижимости до центра Санкт-Петербурга находятся в диапазоне 1322—41 294 м.
Узнаем, на каком расстоянии от центра Санкт-Петербурга находятся объекты недвижимости, расположенные в пределах Санкт-Петербурга.
data.loc[(data['locality_name'] == 'Санкт-Петербург') &
data['city_centers_nearest'].notna(),
'city_centers_nearest'].sort_values().tail()
11652 28644.0 19892 28806.0 16787 29263.0 13031 29343.0 12160 29493.0 Name: city_centers_nearest, dtype: float64
Максимально удалённый от центра Санкт-Петербурга объект недвижимости, всё ещё находящийся в пределах города, расположен на расстоянии 29 493 м.
Узнаем теперь, на каком расстоянии от центра Санкт-Петербурга находятся объекты недвижимости, расположенные вокруг Санкт-Петербурга.
data.loc[data['locality_name'].notna() &
(data['locality_name'] != 'Санкт-Петербург') &
data['city_centers_nearest'].notna(),
'city_centers_nearest'].sort_values().head()
18432 17012.0 6359 17017.0 8392 17231.0 4760 17231.0 1386 17231.0 Name: city_centers_nearest, dtype: float64
Самый ближайший к центру Санкт-Петербурга объект недвижимости, расположенный за его пределами, находится на расстоянии 17 012 м. Таким образом, все объекты недвижимости, расположенные на расстоянии менее 17 012 м, находятся в Санкт-Петербурге.
Выясним теперь, где могут быть расположены объекты недвижимости, расстояние от которых до центра Санкт-Петербурга находится в диапазоне 17 369—41 294 м.
Определим местонахождение объектов недвижимости, расположенных от центра Санкт-Петербурга на расстоянии 17 369 м и от аэропорта на расстоянии 22 041 м.
data.loc[data['locality_name'].notna() &
(data['city_centers_nearest'] == 17369) &
(data['airports_nearest'] == 22041),
'locality_name'].unique()
array(['Санкт-Петербург'], dtype=object)
Определим местонахождение объектов недвижимости, расположенных от центра Санкт-Петербурга на расстоянии 23 659 м и от аэропорта на расстоянии 20 234 м.
data.loc[data['locality_name'].notna() &
(data['city_centers_nearest'] > 23630) &
(data['city_centers_nearest'] < 23690) &
(data['airports_nearest'] > 20200) &
(data['airports_nearest'] < 20260),
'locality_name'].unique()
array(['Санкт-Петербург'], dtype=object)
Для всех объектов недвижимости, расстояние от которых до центра Санкт-Петербурга меньше 23 660 м, указываем местонахождение "Санкт-Петербург", тип населённого пункта — "город".
data.loc[data['locality_name'].isna() &
(data['city_centers_nearest'] < 23660),
'locality_name'] = data['locality_name'].fillna('Санкт-Петербург')
data.loc[data['locality_type'].isna() &
(data['city_centers_nearest'] < 23660),
'locality_type'] = data['locality_type'].fillna('город')
Определим местонахождение объектов недвижимости, расположенных от центра Санкт-Петербурга на расстоянии 31 813 м и 31 897 м и от аэропорта на расстоянии 19 756 м и 19 744 м, соответственно, вокруг которых нет парков.
data.loc[data['locality_name'].notna() &
(data['city_centers_nearest'] > 31600) &
(data['city_centers_nearest'] < 32000) &
(data['airports_nearest'] > 19400) &
(data['airports_nearest'] < 19900) &
(data['parks_around_3000'] == 0),
'locality_name'].unique()
array(['Пушкин'], dtype=object)
data.loc[data['locality_name'].notna() &
(data['locality_name'] == 'Пушкин'),
'locality_type'].unique()
array(['город'], dtype=object)
Для объектов недвижимости, расположенных от центра Санкт-Петербурга на расстоянии 31 813 м и 31 897 м, указываем местонахождение "Пушкин", тип населённого пункта — "город".
data.loc[data['locality_name'].isna() &
((data['city_centers_nearest'] == 31813) |
(data['city_centers_nearest'] == 31897)),
'locality_name'] = data['locality_name'].fillna('Пушкин')
data.loc[data['locality_type'].isna() &
((data['city_centers_nearest'] == 31813) |
(data['city_centers_nearest'] == 31897)),
'locality_type'] = data['locality_type'].fillna('город')
Определим местонахождение объектов недвижимости, расположенных от центра Санкт-Петербурга на расстоянии 41 294 м и от аэропорта на расстоянии 60 195 м, вокруг которых нет водоёмов.
data.loc[data['locality_name'].notna() &
(data['city_centers_nearest'] > 39000) &
(data['city_centers_nearest'] < 43000) &
(data['airports_nearest'] > 58000) &
(data['airports_nearest'] < 62000) &
(data['ponds_around_3000'] == 0),
'locality_name'].unique()
array(['Репино'], dtype=object)
data.loc[data['locality_name'].notna() &
(data['locality_name'] == 'Репино'),
'locality_type'].unique()
array(['посёлок'], dtype=object)
Для объектов недвижимости, расположенных от центра Санкт-Петербурга на расстоянии 41 294 м, указываем местонахождение "Репино", тип населённого пункта — "посёлок".
data.loc[data['locality_name'].isna() &
(data['city_centers_nearest'] == 41294),
'locality_name'] = data['locality_name'].fillna('Репино')
data.loc[data['locality_type'].isna() &
(data['city_centers_nearest'] == 41294),
'locality_type'] = data['locality_type'].fillna('посёлок')
len(data[data['locality_name'].isna() & data['city_centers_nearest'].notna()])
0
Ещё для 8 объектов недвижимости не указано название населённого пункта, но для них также отсутствуют иные картографические данные.
columns = ['floors_total', 'locality_name', 'city_centers_nearest',
'airports_nearest', 'parks_around_3000', 'ponds_around_3000']
data[columns][data['locality_name'].isna()]
| floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | ponds_around_3000 | |
|---|---|---|---|---|---|---|
| 2033 | 4.0 | NaN | NaN | NaN | NaN | NaN |
| 14342 | 4.0 | NaN | NaN | NaN | NaN | NaN |
| 17535 | 9.0 | NaN | NaN | NaN | NaN | NaN |
| 20382 | 5.0 | NaN | NaN | NaN | NaN | NaN |
| 20590 | 4.0 | NaN | NaN | NaN | NaN | NaN |
| 21715 | 9.0 | NaN | NaN | NaN | NaN | NaN |
| 21898 | 9.0 | NaN | NaN | NaN | NaN | NaN |
| 22717 | 16.0 | NaN | NaN | NaN | NaN | NaN |
Поскольку не удаётся с большой долей вероятности предположить местонахождение этих объектов, записи о данных объектах необходимо удалить. И необходимо убедиться, что изменения в данных не привели к ошибкам.
data.drop(index=data[data['locality_name'].isna()].index,
inplace=True)
data['locality_name'].isna().sum()
0
data['locality_type'].isna().sum()
0
list(data['locality_name'].sort_values().unique())
['Агалатово', 'Александровская', 'Алексеевка', 'Аннино', 'Аро', 'Барышево', 'Батово', 'Бегуницы', 'Белогорка', 'Белоостров', 'Бокситогорск', 'Большая Вруда', 'Большая Ижора', 'Большая Пустомержа', 'Большие Колпаны', 'Большое Рейзино', 'Большой Сабск', 'Бор', 'Борисова Грива', 'Бугры', 'Будогощь', 'Ваганово', 'Важины', 'Вартемяги', 'Вахнова Кара', 'Вещево', 'Виллози', 'Вознесенье', 'Возрождение', 'Войсковицы', 'Войскорово', 'Володарское', 'Волосово', 'Волхов', 'Всеволожск', 'Выборг', 'Вырица', 'Выскатка', 'Высокоключевой', 'Высоцк', 'Гаврилово', 'Гарболово', 'Гатчина', 'Гладкое', 'Глажево', 'Глебычево', 'Глинка', 'Гончарово', 'Горбунки', 'Гостилицы', 'Громово', 'Дзержинского', 'Дружная Горка', 'Дружноселье', 'Дубровка', 'Елизаветино', 'Ефимовский', 'Жилгородок', 'Житково', 'Заводской', 'Заклинье', 'Заневка', 'Запорожское', 'Зеленогорск', 'Зимитицы', 'Ивангород', 'Извара', 'Ильичёво', 'Иссад', 'Калитино', 'Каложицы', 'Кальтино', 'Каменногорск', 'Камышовка', 'Каськово', 'Келози', 'Кикерино', 'Кингисепп', 'Кингисеппский', 'Кипень', 'Кириши', 'Кировск', 'Кирпичное', 'Кисельня', 'Кобралово', 'Кобринское', 'Колпино', 'Колтуши', 'Коммунар', 'Коммунары', 'Кондратьево', 'Копорье', 'Коркино', 'Корнево', 'Коробицыно', 'Котельский', 'Котлы', 'Красная Долина', 'Красное Село', 'Красносельское', 'Красный Бор', 'Кривко', 'Кронштадт', 'Кудрово', 'Кузнечное', 'Кузьмолово', 'Кузьмоловский', 'Курковицы', 'Куровицы', 'Куттузи', 'Лаврики', 'Лаголово', 'Лампово', 'Лебяжье', 'Левашово', 'Ленинское', 'Лесколово', 'Лесное', 'Лесогорский', 'Лисий Нос', 'Лодейное Поле', 'Ломоносов', 'Лопухинка', 'Луга', 'Лужайка', 'Лукаши', 'Лупполово', 'Любань', 'Малое Верево', 'Малое Карлино', 'Малые Колпаны', 'Мануйлово', 'Мга', 'Мельниково', 'Меньково', 'Металлострой', 'Мины', 'Мистолово', 'Мичуринское', 'Молодцово', 'Молодёжное', 'Мурино', 'Мыза-Ивановка', 'Назия', 'Ненимяки', 'Нижние Осельки', 'Нижняя', 'Низино', 'Никольский', 'Никольское', 'Новая Ладога', 'Новогорелово', 'Новое Девяткино', 'Новолисино', 'Новоселье', 'Новый Свет', 'Новый Учхоз', 'Нурма', 'Оредеж', 'Оржицы', 'Отрадное', 'Павлово', 'Павловск', 'Пансионат Зелёный Бор', 'Парголово', 'Парицы', 'Паша', 'Пельгора', 'Пеники', 'Первомайское', 'Перово', 'Песочный', 'Петергоф', 'Петро-Славянка', 'Петровское', 'Пижма', 'Пикалёво', 'Пикколово', 'Платформа 69-й километр', 'Плодовое', 'Плоское', 'Победа', 'Подпорожье', 'Поляны', 'Понтонный', 'Почап', 'Починок', 'Приветнинское', 'Пригородный', 'Приладожский', 'Приморск', 'Приозерск', 'Пудомяги', 'Пудость', 'Пустынка', 'Путилово', 'Пушкин', 'Пушное', 'Пчева', 'Пчевжа', 'Рабитицы', 'Разбегаево', 'Раздолье', 'Разметелево', 'Рапполово', 'Рахья', 'Реброво', 'Репино', 'Рождествено', 'Романовка', 'Ромашки', 'Ропша', 'Рощино', 'Русско', 'Русско-Высоцкое', 'Рябово', 'Санкт-Петербург', 'Сапёрное', 'Сапёрный', 'Светогорск', 'Свирь', 'Свирьстрой', 'Севастьяново', 'Селезнёво', 'Сельцо', 'Семиозерье', 'Семрино', 'Серебрянский', 'Сертолово', 'Сестрорецк', 'Сиверский', 'Сижно', 'Синявино', 'Сланцы', 'Снегирёвка', 'Советский', 'Совхозный', 'Сосново', 'Сосновый Бор', 'Старая', 'Старая Ладога', 'Старая Малукса', 'Старая Пустошь', 'Старое Хинколово', 'Старополье', 'Старосиверская', 'Старые Бегуницы', 'Стеклянный', 'Стрельна', 'Суйда', 'Сумино', 'Суоранда', 'Суходолье', 'Сяськелево', 'Сясьстрой', 'Тайцы', 'Тарасово', 'Тельмана', 'Терволово', 'Терпилицы', 'Тихвин', 'Тихковицы', 'Тойворово', 'Токсово', 'Торковичи', 'Торосово', 'Торошковичи', 'Торфяное', 'Тосно', 'Трубников Бор', 'Тёсово-4', 'Углово', 'Ульяновка', 'Усть-Ижора', 'Усть-Луга', 'Ушаки', 'Фалилеево', 'Форносово', 'Форт Красная Горка', 'Фёдоровское', 'Хапо-Ое', 'Хязельки', 'Цвелодубово', 'Цвылёво', 'Чудской Бор', 'Шлиссельбург', 'Шпаньково', 'Шугозеро', 'Шум', 'Шушары', 'Щеглово', 'Юкки', 'Ялгино', 'Яльгелево', 'Ям-Тесово', 'Янино-1', 'имени Морозова', 'имени Свердлова']
data['locality_type'].sort_values().unique()
array(['город', 'городской посёлок', 'деревня', 'посёлок',
'посёлок при железнодорожной станции', 'село'], dtype=object)
show_na()
| Всего пропусков | % | |
|---|---|---|
| parks_nearest | 15455 | 65.9 |
| ponds_nearest | 14427 | 61.5 |
| ceiling_height | 9101 | 38.8 |
| airports_nearest | 5455 | 23.2 |
| city_centers_nearest | 5432 | 23.1 |
| ponds_around_3000 | 5431 | 23.1 |
| parks_around_3000 | 5431 | 23.1 |
| days_exposition | 3154 | 13.4 |
| kitchen_area | 2261 | 9.6 |
| living_area | 1902 | 8.1 |
| floors_total | 86 | 0.4 |
| total_images | 0 | 0.0 |
| locality_name | 0 | 0.0 |
| open_plan | 0 | 0.0 |
| balcony | 0 | 0.0 |
| last_price | 0 | 0.0 |
| studio | 0 | 0.0 |
| is_apartment | 0 | 0.0 |
| floor | 0 | 0.0 |
| rooms | 0 | 0.0 |
| first_day_exposition | 0 | 0.0 |
| total_area | 0 | 0.0 |
| locality_type | 0 | 0.0 |
Среди значений признака parks_around_3000 есть значение 0, которое является меткой, обозначающей отсутствие парка в радиусе 3 км от объекта недвижимости.
data['parks_around_3000'].sort_values().unique()
array([ 0., 1., 2., 3., nan])
Узнаем, в каком количестве записей указано количество парков в радиусе 3 км равное 0, но не указано расстояние до них.
len(data[data['parks_nearest'].isna() & (data['parks_around_3000'] == 0)])
10024
10 024 объекта недвижимости не имеют в радиусе 3 км ни одного парка. Для этих случаев заполним признак parks_nearest значением 0, которое с одной стороны не будет противоречить физической природе величины (расстояние есть величина неотрицательная), а с другой отличаться от допустимых значений, установленных критерием, что расстояние до ближайшего парка не должно быть меньше 10 м.
data.loc[data['parks_nearest'].isna() &
(data['parks_around_3000'] == 0),
'parks_nearest'] = data.loc[data['parks_nearest'].isna() &
(data['parks_around_3000'] == 0),
'parks_nearest'].fillna(0)
len(data[data['parks_nearest'].isna() & (data['parks_around_3000'] == 0)])
0
show_na()
| Всего пропусков | % | |
|---|---|---|
| ponds_nearest | 14427 | 61.5 |
| ceiling_height | 9101 | 38.8 |
| airports_nearest | 5455 | 23.2 |
| city_centers_nearest | 5432 | 23.1 |
| ponds_around_3000 | 5431 | 23.1 |
| parks_nearest | 5431 | 23.1 |
| parks_around_3000 | 5431 | 23.1 |
| days_exposition | 3154 | 13.4 |
| kitchen_area | 2261 | 9.6 |
| living_area | 1902 | 8.1 |
| floors_total | 86 | 0.4 |
| total_images | 0 | 0.0 |
| locality_name | 0 | 0.0 |
| open_plan | 0 | 0.0 |
| balcony | 0 | 0.0 |
| last_price | 0 | 0.0 |
| studio | 0 | 0.0 |
| is_apartment | 0 | 0.0 |
| floor | 0 | 0.0 |
| rooms | 0 | 0.0 |
| first_day_exposition | 0 | 0.0 |
| total_area | 0 | 0.0 |
| locality_type | 0 | 0.0 |
Среди значений признака ponds_around_3000 есть значение 0, которое является меткой, обозначающей отсутствие водоёма в радиусе 3 км от объекта недвижимости.
data['ponds_around_3000'].sort_values().unique()
array([ 0., 1., 2., 3., nan])
Узнаем, в каком количестве записей указано количество водоёмов в радиусе 3 км равное 0, но не указано расстояние до них.
len(data[data['ponds_nearest'].isna() & (data['ponds_around_3000'] == 0)])
8996
8996 объектов недвижимости не имеют в радиусе 3 км ни одного водоёма. Для этих случаев заполним признак ponds_nearest значением 0, которое с одной стороны не будет противоречить физической природе величины (расстояние есть величина неотрицательная), а с другой — как и для признака parks_nearest — отличаться от значения 10 м.
data.loc[data['ponds_nearest'].isna() &
(data['ponds_around_3000'] == 0),
'ponds_nearest'] = data.loc[data['ponds_nearest'].isna() &
(data['ponds_around_3000'] == 0),
'ponds_nearest'].fillna(0)
len(data[data['ponds_nearest'].isna() & (data['ponds_around_3000'] == 0)])
0
show_na()
| Всего пропусков | % | |
|---|---|---|
| ceiling_height | 9101 | 38.8 |
| airports_nearest | 5455 | 23.2 |
| city_centers_nearest | 5432 | 23.1 |
| ponds_nearest | 5431 | 23.1 |
| ponds_around_3000 | 5431 | 23.1 |
| parks_nearest | 5431 | 23.1 |
| parks_around_3000 | 5431 | 23.1 |
| days_exposition | 3154 | 13.4 |
| kitchen_area | 2261 | 9.6 |
| living_area | 1902 | 8.1 |
| floors_total | 86 | 0.4 |
| total_images | 0 | 0.0 |
| locality_name | 0 | 0.0 |
| open_plan | 0 | 0.0 |
| balcony | 0 | 0.0 |
| last_price | 0 | 0.0 |
| studio | 0 | 0.0 |
| is_apartment | 0 | 0.0 |
| floor | 0 | 0.0 |
| rooms | 0 | 0.0 |
| first_day_exposition | 0 | 0.0 |
| total_area | 0 | 0.0 |
| locality_type | 0 | 0.0 |
В 5432 записях не указано расстояние до центра Санкт-Петербурга. Из них только одна запись имеет данные о расстоянии до аэропорта.
columns = ['floors_total', 'locality_name',
'city_centers_nearest', 'airports_nearest']
data[columns][data['city_centers_nearest'].isna() &
data['airports_nearest'].notna()]
| floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|
| 20190 | 3.0 | Пушкин | NaN | 15527.0 |
Теперь определим местонахождение объектов недвижимости в Пушкине, расположенных от аэропорта на расстоянии 15 527 м.
data[columns][(data['locality_name'] == 'Пушкин') &
(data['airports_nearest'] > 15500) &
(data['airports_nearest'] < 15600)] \
.sort_values('airports_nearest')
| floors_total | locality_name | city_centers_nearest | airports_nearest | |
|---|---|---|---|---|
| 17214 | 3.0 | Пушкин | 27673.0 | 15520.0 |
| 4870 | 4.0 | Пушкин | 27677.0 | 15523.0 |
| 20190 | 3.0 | Пушкин | NaN | 15527.0 |
| 8997 | 4.0 | Пушкин | 27704.0 | 15550.0 |
| 12526 | 3.0 | Пушкин | 27734.0 | 15580.0 |
| 20314 | 4.0 | Пушкин | 27749.0 | 15595.0 |
Заметим, что расстояния от зданий до центра Санкт-Петербурга изменяются на такую же величину, что и расстояния до аэропорта. Кроме того, этажность домов составляет 3—4 этажа. Вероятно, дома располагаются рядом: на одной улице или в одном микрорайоне. Поэтому при изменении расстояния до аэропорта на (15 527 м − 15 523 м) = 4 м, расстояние до центра Санкт-Петербурга также должно измениться на 4 м, и составит 27 681 м.
Заполним отсутствующее значение расстояния до центра Санкт-Петербурга значением 27 681 м.
data.loc[data['city_centers_nearest'].isna() &
data['airports_nearest'].notna(),
'city_centers_nearest'] = 27681
show_na()
| Всего пропусков | % | |
|---|---|---|
| ceiling_height | 9101 | 38.8 |
| airports_nearest | 5455 | 23.2 |
| ponds_nearest | 5431 | 23.1 |
| ponds_around_3000 | 5431 | 23.1 |
| parks_nearest | 5431 | 23.1 |
| parks_around_3000 | 5431 | 23.1 |
| city_centers_nearest | 5431 | 23.1 |
| days_exposition | 3154 | 13.4 |
| kitchen_area | 2261 | 9.6 |
| living_area | 1902 | 8.1 |
| floors_total | 86 | 0.4 |
| total_images | 0 | 0.0 |
| locality_name | 0 | 0.0 |
| open_plan | 0 | 0.0 |
| balcony | 0 | 0.0 |
| last_price | 0 | 0.0 |
| studio | 0 | 0.0 |
| is_apartment | 0 | 0.0 |
| floor | 0 | 0.0 |
| rooms | 0 | 0.0 |
| first_day_exposition | 0 | 0.0 |
| total_area | 0 | 0.0 |
| locality_type | 0 | 0.0 |
В 5463 записях не указано расстояние до аэропорта Пулково. Из них только 24 записи имеют сведения о расстоянии до центра Санкт-Петербурга и другие картографические данные.
data.loc[data['airports_nearest'].isna() &
data['city_centers_nearest'].notna(),
'city_centers_nearest'].count()
24
columns = ['floors_total', 'locality_name', 'city_centers_nearest',
'airports_nearest', 'parks_around_3000', 'parks_nearest',
'ponds_around_3000', 'ponds_nearest']
data[columns][data['airports_nearest'].isna() &
data['city_centers_nearest'].notna()] \
.sort_values('city_centers_nearest')
| floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|
| 9880 | 5.0 | Санкт-Петербург | 4892.0 | NaN | 0.0 | 0.0 | 2.0 | 369.0 |
| 7521 | 7.0 | Санкт-Петербург | 5735.0 | NaN | 2.0 | 110.0 | 0.0 | 0.0 |
| 8018 | 7.0 | Санкт-Петербург | 5735.0 | NaN | 2.0 | 110.0 | 0.0 | 0.0 |
| 8628 | 6.0 | Санкт-Петербург | 5735.0 | NaN | 2.0 | 110.0 | 0.0 | 0.0 |
| 13106 | 7.0 | Санкт-Петербург | 5735.0 | NaN | 2.0 | 110.0 | 0.0 | 0.0 |
| 12401 | 7.0 | Санкт-Петербург | 5735.0 | NaN | 2.0 | 110.0 | 0.0 | 0.0 |
| 11457 | 10.0 | Санкт-Петербург | 9734.0 | NaN | 2.0 | 469.0 | 3.0 | 263.0 |
| 974 | 7.0 | Санкт-Петербург | 9734.0 | NaN | 2.0 | 469.0 | 3.0 | 263.0 |
| 21769 | 25.0 | Санкт-Петербург | 9734.0 | NaN | 2.0 | 469.0 | 3.0 | 263.0 |
| 9054 | 10.0 | Санкт-Петербург | 9734.0 | NaN | 2.0 | 469.0 | 3.0 | 263.0 |
| 16825 | 16.0 | Санкт-Петербург | 9734.0 | NaN | 2.0 | 469.0 | 3.0 | 263.0 |
| 14276 | 25.0 | Санкт-Петербург | 9734.0 | NaN | 2.0 | 469.0 | 3.0 | 263.0 |
| 21075 | 5.0 | Санкт-Петербург | 11246.0 | NaN | 0.0 | 0.0 | 0.0 | 0.0 |
| 23124 | 5.0 | Санкт-Петербург | 11246.0 | NaN | 0.0 | 0.0 | 0.0 | 0.0 |
| 11446 | 5.0 | Санкт-Петербург | 11835.0 | NaN | 1.0 | 267.0 | 1.0 | 601.0 |
| 16470 | 19.0 | Санкт-Петербург | 13355.0 | NaN | 1.0 | 735.0 | 0.0 | 0.0 |
| 16927 | 23.0 | Санкт-Петербург | 13355.0 | NaN | 1.0 | 735.0 | 0.0 | 0.0 |
| 18222 | 23.0 | Санкт-Петербург | 13355.0 | NaN | 1.0 | 735.0 | 0.0 | 0.0 |
| 18557 | 19.0 | Санкт-Петербург | 13355.0 | NaN | 1.0 | 735.0 | 0.0 | 0.0 |
| 7542 | 23.0 | Санкт-Петербург | 13355.0 | NaN | 1.0 | 735.0 | 0.0 | 0.0 |
| 2415 | 23.0 | Санкт-Петербург | 13355.0 | NaN | 1.0 | 735.0 | 0.0 | 0.0 |
| 22790 | 23.0 | Санкт-Петербург | 13355.0 | NaN | 1.0 | 735.0 | 0.0 | 0.0 |
| 733 | 21.0 | Санкт-Петербург | 13355.0 | NaN | 1.0 | 735.0 | 0.0 | 0.0 |
| 10669 | 5.0 | Санкт-Петербург | 21377.0 | NaN | 0.0 | 0.0 | 0.0 | 0.0 |
Все объекты расположены в Санкт-Петербурге на расстоянии от центра города в диапазоне 4892—21 377 м.
Выясним, на каком расстоянии от аэропорта находятся объекты недвижимости в Санкт-Петербурге, расположенные на расстоянии 4892 м от центра города, вокруг которых нет парков, но есть 2 водоёма.
data[columns][(data['locality_name'] == 'Санкт-Петербург') &
(data['city_centers_nearest'] > 4850) &
(data['city_centers_nearest'] < 4930) &
(data['ponds_around_3000'] == 2) &
(data['parks_around_3000'] == 0)] \
.sort_values('city_centers_nearest')
| floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|
| 351 | 5.0 | Санкт-Петербург | 4855.0 | 32758.0 | 0.0 | 0.0 | 2.0 | 519.0 |
| 9880 | 5.0 | Санкт-Петербург | 4892.0 | NaN | 0.0 | 0.0 | 2.0 | 369.0 |
| 13607 | 5.0 | Санкт-Петербург | 4920.0 | 32273.0 | 0.0 | 0.0 | 2.0 | 834.0 |
Заменим отсутствующее значение на значение 32 500 м (среднее арифметическое значение, рассчитанное с точностью до 100 м).
data.loc[(data['locality_name'] == 'Санкт-Петербург') &
(data['city_centers_nearest'] == 4892),
'airports_nearest'] = 32500
data[columns][(data['locality_name'] == 'Санкт-Петербург') &
(data['city_centers_nearest'] == 4892)]
| floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|
| 9880 | 5.0 | Санкт-Петербург | 4892.0 | 32500.0 | 0.0 | 0.0 | 2.0 | 369.0 |
Выясним, на каком расстоянии от аэропорта находятся объекты недвижимости в Санкт-Петербурге, расположенные на расстоянии 5735 м от центра города, вокруг которых нет водоёмов, но есть 2 парка.
data[columns][(data['locality_name'] == 'Санкт-Петербург') &
(data['city_centers_nearest'] > 5700) &
(data['city_centers_nearest'] < 5770) &
(data['parks_around_3000'] == 2) &
(data['ponds_around_3000'] == 0)] \
.sort_values('city_centers_nearest')
| floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|
| 1212 | 4.0 | Санкт-Петербург | 5718.0 | 25300.0 | 2.0 | 381.0 | 0.0 | 0.0 |
| 20389 | 4.0 | Санкт-Петербург | 5718.0 | 25300.0 | 2.0 | 381.0 | 0.0 | 0.0 |
| 7521 | 7.0 | Санкт-Петербург | 5735.0 | NaN | 2.0 | 110.0 | 0.0 | 0.0 |
| 8018 | 7.0 | Санкт-Петербург | 5735.0 | NaN | 2.0 | 110.0 | 0.0 | 0.0 |
| 8628 | 6.0 | Санкт-Петербург | 5735.0 | NaN | 2.0 | 110.0 | 0.0 | 0.0 |
| 12401 | 7.0 | Санкт-Петербург | 5735.0 | NaN | 2.0 | 110.0 | 0.0 | 0.0 |
| 13106 | 7.0 | Санкт-Петербург | 5735.0 | NaN | 2.0 | 110.0 | 0.0 | 0.0 |
| 736 | 6.0 | Санкт-Петербург | 5741.0 | 25323.0 | 2.0 | 393.0 | 0.0 | 0.0 |
| 22025 | 6.0 | Санкт-Петербург | 5741.0 | 25323.0 | 2.0 | 393.0 | 0.0 | 0.0 |
| 14879 | 5.0 | Санкт-Петербург | 5744.0 | 16869.0 | 2.0 | 300.0 | 0.0 | 0.0 |
| 16169 | 6.0 | Санкт-Петербург | 5746.0 | 25469.0 | 2.0 | 93.0 | 0.0 | 0.0 |
| 8842 | 8.0 | Санкт-Петербург | 5765.0 | 25846.0 | 2.0 | 250.0 | 0.0 | 0.0 |
| 13816 | 8.0 | Санкт-Петербург | 5765.0 | 25846.0 | 2.0 | 250.0 | 0.0 | 0.0 |
Близкими по расположению являются 6—7-этажные здания, которые расположены на расстоянии 25 300—25 469 м от аэропорта. Заполним отсутствующее значение на значение 25 350 м.
data.loc[(data['city_centers_nearest'] == 5735) &
(data['locality_name'] == 'Санкт-Петербург'),
'airports_nearest'] = 25350
data[columns][(data['locality_name'] == 'Санкт-Петербург') &
(data['city_centers_nearest'] == 5735)]
| floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|
| 7521 | 7.0 | Санкт-Петербург | 5735.0 | 25350.0 | 2.0 | 110.0 | 0.0 | 0.0 |
| 8018 | 7.0 | Санкт-Петербург | 5735.0 | 25350.0 | 2.0 | 110.0 | 0.0 | 0.0 |
| 8628 | 6.0 | Санкт-Петербург | 5735.0 | 25350.0 | 2.0 | 110.0 | 0.0 | 0.0 |
| 12401 | 7.0 | Санкт-Петербург | 5735.0 | 25350.0 | 2.0 | 110.0 | 0.0 | 0.0 |
| 13106 | 7.0 | Санкт-Петербург | 5735.0 | 25350.0 | 2.0 | 110.0 | 0.0 | 0.0 |
Выясним, на каком расстоянии от аэропорта находятся объекты недвижимости в Санкт-Петербурге, расположенные на расстоянии 9734 м от центра города, вокруг которых есть 2 парка и 3 водоёма.
data[columns][(data['locality_name'] == 'Санкт-Петербург') &
(data['city_centers_nearest'] > 9700) &
(data['city_centers_nearest'] < 9770) &
(data['parks_around_3000'] == 2) &
(data['ponds_around_3000'] == 3)] \
.sort_values('city_centers_nearest')
| floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|
| 13582 | 5.0 | Санкт-Петербург | 9702.0 | 35836.0 | 2.0 | 588.0 | 3.0 | 316.0 |
| 15153 | 5.0 | Санкт-Петербург | 9724.0 | 36011.0 | 2.0 | 473.0 | 3.0 | 483.0 |
| 974 | 7.0 | Санкт-Петербург | 9734.0 | NaN | 2.0 | 469.0 | 3.0 | 263.0 |
| 9054 | 10.0 | Санкт-Петербург | 9734.0 | NaN | 2.0 | 469.0 | 3.0 | 263.0 |
| 11457 | 10.0 | Санкт-Петербург | 9734.0 | NaN | 2.0 | 469.0 | 3.0 | 263.0 |
| 14276 | 25.0 | Санкт-Петербург | 9734.0 | NaN | 2.0 | 469.0 | 3.0 | 263.0 |
| 16825 | 16.0 | Санкт-Петербург | 9734.0 | NaN | 2.0 | 469.0 | 3.0 | 263.0 |
| 21769 | 25.0 | Санкт-Петербург | 9734.0 | NaN | 2.0 | 469.0 | 3.0 | 263.0 |
Заменим отсутствующее значение на значение 35 900 м (среднее арифметическое значение, рассчитанное с точностью до 100 м).
data.loc[(data['city_centers_nearest'] == 9734) &
(data['locality_name'] == 'Санкт-Петербург'),
'airports_nearest'] = 35900
data[columns][(data['locality_name'] == 'Санкт-Петербург') &
(data['city_centers_nearest'] == 9734)]
| floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|
| 974 | 7.0 | Санкт-Петербург | 9734.0 | 35900.0 | 2.0 | 469.0 | 3.0 | 263.0 |
| 9054 | 10.0 | Санкт-Петербург | 9734.0 | 35900.0 | 2.0 | 469.0 | 3.0 | 263.0 |
| 10959 | 5.0 | Санкт-Петербург | 9734.0 | 35900.0 | 0.0 | 0.0 | 1.0 | 431.0 |
| 11457 | 10.0 | Санкт-Петербург | 9734.0 | 35900.0 | 2.0 | 469.0 | 3.0 | 263.0 |
| 14276 | 25.0 | Санкт-Петербург | 9734.0 | 35900.0 | 2.0 | 469.0 | 3.0 | 263.0 |
| 16825 | 16.0 | Санкт-Петербург | 9734.0 | 35900.0 | 2.0 | 469.0 | 3.0 | 263.0 |
| 19430 | 5.0 | Санкт-Петербург | 9734.0 | 35900.0 | 0.0 | 0.0 | 1.0 | 431.0 |
| 21769 | 25.0 | Санкт-Петербург | 9734.0 | 35900.0 | 2.0 | 469.0 | 3.0 | 263.0 |
Выясним, на каком расстоянии от аэропорта находятся 5-этажные здания в Санкт-Петербурге, расположенные на расстоянии 11 246 м от центра города, вокруг которых нет парков и водоёмов.
data[columns][(data['locality_name'] == 'Санкт-Петербург') &
(data['city_centers_nearest'] > 11200) &
(data['city_centers_nearest'] < 11300) &
(data['parks_around_3000'] == 0) &
(data['ponds_around_3000'] == 0) &
(data['floors_total'] == 5)] \
.sort_values('airports_nearest')
| floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|
| 4687 | 5.0 | Санкт-Петербург | 11246.0 | 9823.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 13888 | 5.0 | Санкт-Петербург | 11282.0 | 10875.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 18144 | 5.0 | Санкт-Петербург | 11282.0 | 10875.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 6706 | 5.0 | Санкт-Петербург | 11286.0 | 10877.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 3292 | 5.0 | Санкт-Петербург | 11247.0 | 14717.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 5470 | 5.0 | Санкт-Петербург | 11240.0 | 37499.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 20974 | 5.0 | Санкт-Петербург | 11211.0 | 39508.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 17827 | 5.0 | Санкт-Петербург | 11269.0 | 39566.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 17242 | 5.0 | Санкт-Петербург | 11282.0 | 41099.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 23401 | 5.0 | Санкт-Петербург | 11282.0 | 41099.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 21075 | 5.0 | Санкт-Петербург | 11246.0 | NaN | 0.0 | 0.0 | 0.0 | 0.0 |
| 23124 | 5.0 | Санкт-Петербург | 11246.0 | NaN | 0.0 | 0.0 | 0.0 | 0.0 |
Поскольку разброс возможных значений расстояния до аэропорта большой, рассчитаем среднее арифметическое имеющихся значений и заполним этим полученным средним отсутствующие значения.
mean_for_fillna = data.loc[(data['locality_name'] == 'Санкт-Петербург') &
(data['city_centers_nearest'] > 11220) &
(data['city_centers_nearest'] < 11270) &
(data['parks_around_3000'] == 0) &
(data['ponds_around_3000'] == 0) &
(data['floors_total'] == 5),
'airports_nearest'].mean().round(-2)
data.loc[(data['city_centers_nearest'] == 11246) &
(data['locality_name'] == 'Санкт-Петербург'),
'airports_nearest'] = data['airports_nearest'].fillna(mean_for_fillna)
data[columns][(data['locality_name'] == 'Санкт-Петербург') &
(data['city_centers_nearest'] == 11246)]
| floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|
| 4687 | 5.0 | Санкт-Петербург | 11246.0 | 9823.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 13307 | 10.0 | Санкт-Петербург | 11246.0 | 29080.0 | 1.0 | 546.0 | 1.0 | 593.0 |
| 21075 | 5.0 | Санкт-Петербург | 11246.0 | 25400.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 23124 | 5.0 | Санкт-Петербург | 11246.0 | 25400.0 | 0.0 | 0.0 | 0.0 | 0.0 |
Выясним, на каком расстоянии от аэропорта находятся 5-этажные здания в Санкт-Петербурге, расположенные на расстоянии 11 835 м от центра города, вокруг которых есть 1 парк и 1 водоём.
data[columns][(data['locality_name'] == 'Санкт-Петербург') &
(data['city_centers_nearest'] > 11700) &
(data['city_centers_nearest'] < 11870) &
(data['parks_around_3000'] == 1) &
(data['ponds_around_3000'] == 1) &
(data['ponds_nearest'] > 500) &
(data['ponds_nearest'] < 650) &
(data['floors_total'] == 5)] \
.sort_values('city_centers_nearest')
| floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|
| 16634 | 5.0 | Санкт-Петербург | 11792.0 | 14771.0 | 1.0 | 318.0 | 1.0 | 571.0 |
| 22664 | 5.0 | Санкт-Петербург | 11792.0 | 14771.0 | 1.0 | 318.0 | 1.0 | 571.0 |
| 3791 | 5.0 | Санкт-Петербург | 11831.0 | 14730.0 | 1.0 | 322.0 | 1.0 | 596.0 |
| 11446 | 5.0 | Санкт-Петербург | 11835.0 | NaN | 1.0 | 267.0 | 1.0 | 601.0 |
Заменим отсутствующее значение на значение 14 750 м.
data.loc[(data['city_centers_nearest'] == 11835) &
(data['locality_name'] == 'Санкт-Петербург'),
'airports_nearest'] = 14750
data[columns][(data['locality_name'] == 'Санкт-Петербург') &
(data['city_centers_nearest'] == 11835)]
| floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|
| 11446 | 5.0 | Санкт-Петербург | 11835.0 | 14750.0 | 1.0 | 267.0 | 1.0 | 601.0 |
Выясним, на каком расстоянии от аэропорта находятся объекты недвижимости в Санкт-Петербурге, расположенные на расстоянии 13 355 м от центра города, вокруг которых нет водоёмов, но есть 1 парк.
data[columns][(data['locality_name'] == 'Санкт-Петербург') &
(data['city_centers_nearest'] > 13250) &
(data['city_centers_nearest'] < 13450) &
(data['parks_around_3000'] == 1) &
(data['ponds_around_3000'] == 0) &
(data['parks_nearest'] > 650) &
(data['parks_nearest'] < 850)] \
.sort_values('city_centers_nearest')
| floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|
| 733 | 21.0 | Санкт-Петербург | 13355.0 | NaN | 1.0 | 735.0 | 0.0 | 0.0 |
| 18557 | 19.0 | Санкт-Петербург | 13355.0 | NaN | 1.0 | 735.0 | 0.0 | 0.0 |
| 18222 | 23.0 | Санкт-Петербург | 13355.0 | NaN | 1.0 | 735.0 | 0.0 | 0.0 |
| 16927 | 23.0 | Санкт-Петербург | 13355.0 | NaN | 1.0 | 735.0 | 0.0 | 0.0 |
| 16470 | 19.0 | Санкт-Петербург | 13355.0 | NaN | 1.0 | 735.0 | 0.0 | 0.0 |
| 22790 | 23.0 | Санкт-Петербург | 13355.0 | NaN | 1.0 | 735.0 | 0.0 | 0.0 |
| 7542 | 23.0 | Санкт-Петербург | 13355.0 | NaN | 1.0 | 735.0 | 0.0 | 0.0 |
| 2415 | 23.0 | Санкт-Петербург | 13355.0 | NaN | 1.0 | 735.0 | 0.0 | 0.0 |
| 12106 | 13.0 | Санкт-Петербург | 13370.0 | 51443.0 | 1.0 | 805.0 | 0.0 | 0.0 |
| 13857 | 25.0 | Санкт-Петербург | 13370.0 | 51443.0 | 1.0 | 805.0 | 0.0 | 0.0 |
| 19517 | 16.0 | Санкт-Петербург | 13370.0 | 51443.0 | 1.0 | 805.0 | 0.0 | 0.0 |
| 7360 | 25.0 | Санкт-Петербург | 13370.0 | 51443.0 | 1.0 | 805.0 | 0.0 | 0.0 |
| 6562 | 17.0 | Санкт-Петербург | 13370.0 | 51443.0 | 1.0 | 805.0 | 0.0 | 0.0 |
| 18608 | 13.0 | Санкт-Петербург | 13370.0 | 51443.0 | 1.0 | 805.0 | 0.0 | 0.0 |
| 19290 | 16.0 | Санкт-Петербург | 13370.0 | 51443.0 | 1.0 | 805.0 | 0.0 | 0.0 |
| 9257 | 25.0 | Санкт-Петербург | 13370.0 | 51443.0 | 1.0 | 805.0 | 0.0 | 0.0 |
| 14782 | 17.0 | Санкт-Петербург | 13370.0 | 51443.0 | 1.0 | 805.0 | 0.0 | 0.0 |
Заменим отсутствующее значение на значение 51 400 м.
data.loc[(data['city_centers_nearest'] == 13355) &
(data['locality_name'] == 'Санкт-Петербург'),
'airports_nearest'] = 51400
data[columns][(data['locality_name'] == 'Санкт-Петербург') &
(data['city_centers_nearest'] == 13355)]
| floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|
| 733 | 21.0 | Санкт-Петербург | 13355.0 | 51400.0 | 1.0 | 735.0 | 0.0 | 0.0 |
| 2415 | 23.0 | Санкт-Петербург | 13355.0 | 51400.0 | 1.0 | 735.0 | 0.0 | 0.0 |
| 3916 | 5.0 | Санкт-Петербург | 13355.0 | 51400.0 | 2.0 | 186.0 | 2.0 | 347.0 |
| 7542 | 23.0 | Санкт-Петербург | 13355.0 | 51400.0 | 1.0 | 735.0 | 0.0 | 0.0 |
| 16470 | 19.0 | Санкт-Петербург | 13355.0 | 51400.0 | 1.0 | 735.0 | 0.0 | 0.0 |
| 16927 | 23.0 | Санкт-Петербург | 13355.0 | 51400.0 | 1.0 | 735.0 | 0.0 | 0.0 |
| 18222 | 23.0 | Санкт-Петербург | 13355.0 | 51400.0 | 1.0 | 735.0 | 0.0 | 0.0 |
| 18557 | 19.0 | Санкт-Петербург | 13355.0 | 51400.0 | 1.0 | 735.0 | 0.0 | 0.0 |
| 22790 | 23.0 | Санкт-Петербург | 13355.0 | 51400.0 | 1.0 | 735.0 | 0.0 | 0.0 |
Выясним, на каком расстоянии от аэропорта находятся 5-этажные здания в Санкт-Петербурге, расположенные на расстоянии 21 377 м от центра города, вокруг которых нет парков и водоёмов.
data[columns][(data['locality_name'] == 'Санкт-Петербург') &
(data['city_centers_nearest'] > 21000) &
(data['city_centers_nearest'] < 21500) &
(data['parks_around_3000'] == 0) &
(data['ponds_around_3000'] == 0) &
(data['floors_total'] == 5)] \
.sort_values('city_centers_nearest')
| floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|
| 12534 | 5.0 | Санкт-Петербург | 21280.0 | 18118.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 10669 | 5.0 | Санкт-Петербург | 21377.0 | NaN | 0.0 | 0.0 | 0.0 | 0.0 |
| 13764 | 5.0 | Санкт-Петербург | 21497.0 | 17659.0 | 0.0 | 0.0 | 0.0 | 0.0 |
Заменим отсутствующее значение на значение 17 900 м (среднее арифметическое значение, рассчитанное с точностью до 100 м).
data.loc[(data['city_centers_nearest'] == 21377) &
(data['locality_name'] == 'Санкт-Петербург'),
'airports_nearest'] = 17900
data[columns][(data['locality_name'] == 'Санкт-Петербург') &
(data['city_centers_nearest'] == 21377)]
| floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|
| 10669 | 5.0 | Санкт-Петербург | 21377.0 | 17900.0 | 0.0 | 0.0 | 0.0 | 0.0 |
show_na()
| Всего пропусков | % | |
|---|---|---|
| ceiling_height | 9101 | 38.8 |
| ponds_nearest | 5431 | 23.1 |
| ponds_around_3000 | 5431 | 23.1 |
| parks_nearest | 5431 | 23.1 |
| parks_around_3000 | 5431 | 23.1 |
| city_centers_nearest | 5431 | 23.1 |
| airports_nearest | 5431 | 23.1 |
| days_exposition | 3154 | 13.4 |
| kitchen_area | 2261 | 9.6 |
| living_area | 1902 | 8.1 |
| floors_total | 86 | 0.4 |
| total_images | 0 | 0.0 |
| locality_name | 0 | 0.0 |
| open_plan | 0 | 0.0 |
| balcony | 0 | 0.0 |
| last_price | 0 | 0.0 |
| studio | 0 | 0.0 |
| is_apartment | 0 | 0.0 |
| floor | 0 | 0.0 |
| rooms | 0 | 0.0 |
| first_day_exposition | 0 | 0.0 |
| total_area | 0 | 0.0 |
| locality_type | 0 | 0.0 |
В признаке floors_total отсутствуют значения в 86 записях. В 76 из них указаны картографические данные.
columns = ['floor', 'floors_total', 'locality_name', 'city_centers_nearest',
'airports_nearest', 'parks_around_3000', 'parks_nearest',
'ponds_around_3000', 'ponds_nearest']
data[columns][data['floors_total'].isna() &
data['city_centers_nearest'].notna()] \
.sort_values('city_centers_nearest')
| floor | floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 2952 | 6 | NaN | Санкт-Петербург | 3148.0 | 23606.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 10880 | 3 | NaN | Санкт-Петербург | 3252.0 | 20160.0 | 2.0 | 320.0 | 1.0 | 976.0 |
| 22808 | 6 | NaN | Санкт-Петербург | 4529.0 | 19095.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 23590 | 18 | NaN | Санкт-Петербург | 4529.0 | 19095.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 18832 | 6 | NaN | Санкт-Петербург | 4529.0 | 19095.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 12104 | 7 | NaN | Санкт-Петербург | 25866.0 | 47303.0 | 1.0 | 251.0 | 1.0 | 350.0 |
| 10004 | 5 | NaN | Красное Село | 28719.0 | 25295.0 | 3.0 | 362.0 | 0.0 | 0.0 |
| 15989 | 1 | NaN | Красное Село | 28806.0 | 25382.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 8986 | 4 | NaN | Пушкин | 31813.0 | 19659.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 3817 | 1 | NaN | Щеглово | 34085.0 | 61908.0 | 0.0 | 0.0 | 0.0 | 0.0 |
76 rows × 9 columns
Для заполнения значений этажности зданий будем использовать известные значения этажности других зданий, расположенных на тех же расстояниях от центра Санкт-Петербурга и от аэропорта. Если таких зданий окажется несколько, то выбираем самое высокое здание (т. е. здание с максимальной этажностью). Заполняем этажность этим максимальным значением. В случае, если окажется, что этаж, на котором расположен объект недвижимости, выше чем самое высокое здание, то указываем в качестве этажности номер этажа. Таким образом, объект недвижимости получается расположенным на последнем этаже.
# Сделаем срез строк, содержащих отсутствующее значение признака `floors_total`,
# но имеющих данные о расстоянии до центра Санкт-Петербурга и до аэропорта
floors_total_na = data[data['floors_total'].isna() &
data['city_centers_nearest'].notna() &
data['airports_nearest'].notna()]
for index, row in floors_total_na.iterrows(): # Положим в переменные:
distance_to_center = row['city_centers_nearest'] # значение расстояния до центра Санкт-Петербурга
distance_to_airport = row['airports_nearest'] # значение расстояния до аэропорта
floor_number = row['floor'] # номер этажа, на котором расположен объект недвижимости
# Выберем из имеющихся в наборе данных значений признака `floors_total`
# максимальное значение среди всех зданий, расположенных на том же
# расстоянии от аэропорта и центра Санкт-Петербурга,
# что и здание неизвестной этажности
floors_total_value = data.loc[
data['floors_total'].notna() &
(data['city_centers_nearest'] == distance_to_center) &
(data['airports_nearest'] == distance_to_airport),
'floors_total'].max()
if floors_total_value >= floor_number:
# Если этаж, на котором расположен объект недвижимости в здании с
# неизвестной этажностью, меньше максимального значения этажности зданий,
# то заполняем отсутствующее значение максимальным значением
data.loc[data['floors_total'].isna() &
(data['city_centers_nearest'] == distance_to_center) &
(data['airports_nearest'] == distance_to_airport),
'floors_total'] = data['floors_total'].fillna(floors_total_value)
elif floors_total_value < floor_number:
# Если этаж, на котором расположен объект недвижимости в здании с
# неизвестной этажностью, больше максимального значения этажности,
# то заполняем отсутствующее значение максимальным значением среди
# номеров этажей, на которых располагаются объекты недвижимости в
# зданиях с неизвестной этажностью
floor_number_max = floors_total_na.loc[
(floors_total_na['city_centers_nearest'] == distance_to_center) &
(floors_total_na['airports_nearest'] == distance_to_airport),
'floor'].max()
data.loc[data['floors_total'].isna() &
(data['city_centers_nearest'] == distance_to_center) &
(data['airports_nearest'] == distance_to_airport),
'floors_total'] = data['floors_total'].fillna(floor_number_max)
data['floors_total'].sort_values().unique()
array([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12., 13.,
14., 15., 16., 17., 18., 19., 20., 21., 22., 23., 24., 25., 26.,
27., 28., 29., 35., nan])
Выясним, какие значения остались незаполненными.
data[columns][data['floors_total'].isna() &
data['city_centers_nearest'].notna()] \
.sort_values('city_centers_nearest')
| floor | floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 10880 | 3 | NaN | Санкт-Петербург | 3252.0 | 20160.0 | 2.0 | 320.0 | 1.0 | 976.0 |
| 18832 | 6 | NaN | Санкт-Петербург | 4529.0 | 19095.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 22808 | 6 | NaN | Санкт-Петербург | 4529.0 | 19095.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 23590 | 18 | NaN | Санкт-Петербург | 4529.0 | 19095.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 6030 | 24 | NaN | Санкт-Петербург | 14674.0 | 35234.0 | 0.0 | 0.0 | 1.0 | 844.0 |
| 11389 | 7 | NaN | Санкт-Петербург | 14674.0 | 35234.0 | 0.0 | 0.0 | 1.0 | 844.0 |
| 13622 | 21 | NaN | Санкт-Петербург | 14674.0 | 35234.0 | 0.0 | 0.0 | 1.0 | 844.0 |
| 21273 | 19 | NaN | Санкт-Петербург | 14674.0 | 35234.0 | 0.0 | 0.0 | 1.0 | 844.0 |
| 12399 | 4 | NaN | Санкт-Петербург | 18535.0 | 19533.0 | 1.0 | 375.0 | 0.0 | 0.0 |
| 10259 | 5 | NaN | Мурино | 21888.0 | 51553.0 | 0.0 | 0.0 | 2.0 | 133.0 |
| 11425 | 4 | NaN | Мурино | 21888.0 | 51553.0 | 0.0 | 0.0 | 2.0 | 133.0 |
| 15989 | 1 | NaN | Красное Село | 28806.0 | 25382.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 8986 | 4 | NaN | Пушкин | 31813.0 | 19659.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 3817 | 1 | NaN | Щеглово | 34085.0 | 61908.0 | 0.0 | 0.0 | 0.0 | 0.0 |
Выясним, какова этажность зданий в Санкт-Петербурге, расположенных от центра города на расстоянии 3252 м и от аэропорта на расстоянии 20 160 м, вокруг которых есть 2 парка и 1 водоём.
data[columns][(data['city_centers_nearest'] > 3200) &
(data['city_centers_nearest'] < 3300) &
(data['airports_nearest'] > 19000) &
(data['airports_nearest'] < 21000) &
(data['parks_around_3000'] == 2) &
(data['ponds_around_3000'] == 1)] \
.sort_values('city_centers_nearest')
| floor | floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 2122 | 2 | 4.0 | Санкт-Петербург | 3233.0 | 20628.0 | 2.0 | 261.0 | 1.0 | 819.0 |
| 10287 | 1 | 5.0 | Санкт-Петербург | 3238.0 | 20873.0 | 2.0 | 450.0 | 1.0 | 869.0 |
| 10880 | 3 | NaN | Санкт-Петербург | 3252.0 | 20160.0 | 2.0 | 320.0 | 1.0 | 976.0 |
| 9500 | 6 | 6.0 | Санкт-Петербург | 3269.0 | 20904.0 | 2.0 | 482.0 | 1.0 | 849.0 |
Поскольку все найденные значения разные, заполним отсутствующее значение медианным значением — 5.
data.loc[data['floors_total'].isna() &
(data['city_centers_nearest'] == 3252) &
(data['airports_nearest'] == 20160),
'floors_total'] = data['floors_total'].fillna(5)
data[columns][(data['city_centers_nearest'] == 3252) &
(data['airports_nearest'] == 20160)]
| floor | floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 10880 | 3 | 5.0 | Санкт-Петербург | 3252.0 | 20160.0 | 2.0 | 320.0 | 1.0 | 976.0 |
Выясним, какова этажность зданий в Санкт-Петербурге, расположенных от центра города на расстоянии 4529 м и от аэропорта на расстоянии 19 095 м, вокруг которых нет парков и водоёмов.
data[columns][(data['city_centers_nearest'] > 4500) &
(data['city_centers_nearest'] < 4600) &
(data['airports_nearest'] > 18840) &
(data['airports_nearest'] < 19350) &
(data['ponds_around_3000'] == 0) &
(data['parks_around_3000'] == 0)] \
.sort_values('city_centers_nearest')
| floor | floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 6564 | 17 | 19.0 | Санкт-Петербург | 4529.0 | 18934.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 18832 | 6 | NaN | Санкт-Петербург | 4529.0 | 19095.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 22808 | 6 | NaN | Санкт-Петербург | 4529.0 | 19095.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 23590 | 18 | NaN | Санкт-Петербург | 4529.0 | 19095.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 5144 | 19 | 19.0 | Санкт-Петербург | 4530.0 | 18941.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 18701 | 19 | 19.0 | Санкт-Петербург | 4579.0 | 18995.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 19964 | 4 | 19.0 | Санкт-Петербург | 4579.0 | 18995.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 22105 | 19 | 19.0 | Санкт-Петербург | 4579.0 | 18995.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 22172 | 17 | 19.0 | Санкт-Петербург | 4579.0 | 18995.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 13354 | 19 | 19.0 | Санкт-Петербург | 4588.0 | 18995.0 | 0.0 | 0.0 | 0.0 | 0.0 |
Заменим отсутствующее значение на значение 19.
data.loc[data['floors_total'].isna() &
(data['city_centers_nearest'] == 4529) &
(data['airports_nearest'] == 19095),
'floors_total'] = data['floors_total'].fillna(19)
data[columns][(data['city_centers_nearest'] == 4529) &
(data['airports_nearest'] == 19095)]
| floor | floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 18832 | 6 | 19.0 | Санкт-Петербург | 4529.0 | 19095.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 22808 | 6 | 19.0 | Санкт-Петербург | 4529.0 | 19095.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 23590 | 18 | 19.0 | Санкт-Петербург | 4529.0 | 19095.0 | 0.0 | 0.0 | 0.0 | 0.0 |
Выясним, какова этажность зданий в Санкт-Петербурге, расположенных от центра города на расстоянии 14 674 м и от аэропорта на расстоянии 35 234 м, этажность которых составляет не менее 24 этажей.
data[columns][(data['city_centers_nearest'] > 14600) &
(data['city_centers_nearest'] < 14800) &
(data['airports_nearest'] > 35100) &
(data['airports_nearest'] < 35300) &
(data['floors_total'] >= 24) &
(data['ponds_around_3000'] == 1)] \
.sort_values('city_centers_nearest')
| floor | floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 4758 | 3 | 25.0 | Санкт-Петербург | 14772.0 | 35257.0 | 0.0 | 0.0 | 1.0 | 865.0 |
| 16888 | 19 | 25.0 | Санкт-Петербург | 14772.0 | 35257.0 | 0.0 | 0.0 | 1.0 | 865.0 |
| 17232 | 11 | 25.0 | Санкт-Петербург | 14772.0 | 35257.0 | 0.0 | 0.0 | 1.0 | 865.0 |
| 19206 | 19 | 24.0 | Санкт-Петербург | 14772.0 | 35257.0 | 0.0 | 0.0 | 1.0 | 865.0 |
| 19293 | 12 | 25.0 | Санкт-Петербург | 14772.0 | 35257.0 | 0.0 | 0.0 | 1.0 | 865.0 |
| 22050 | 11 | 25.0 | Санкт-Петербург | 14772.0 | 35257.0 | 0.0 | 0.0 | 1.0 | 865.0 |
Заменим отсутствующее значение на значение моды — 25.
data.loc[data['floors_total'].isna() &
(data['city_centers_nearest'] == 14674) &
(data['airports_nearest'] == 35234),
'floors_total'] = data['floors_total'].fillna(25)
data[columns][(data['city_centers_nearest'] == 14674) &
(data['airports_nearest'] == 35234)]
| floor | floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 6030 | 24 | 25.0 | Санкт-Петербург | 14674.0 | 35234.0 | 0.0 | 0.0 | 1.0 | 844.0 |
| 11389 | 7 | 25.0 | Санкт-Петербург | 14674.0 | 35234.0 | 0.0 | 0.0 | 1.0 | 844.0 |
| 13622 | 21 | 25.0 | Санкт-Петербург | 14674.0 | 35234.0 | 0.0 | 0.0 | 1.0 | 844.0 |
| 21273 | 19 | 25.0 | Санкт-Петербург | 14674.0 | 35234.0 | 0.0 | 0.0 | 1.0 | 844.0 |
Выясним, какова этажность зданий в Санкт-Петербурге, расположенных от центра города на расстоянии 18 535 м и от аэропорта на расстоянии 19 533 м, вокруг которых есть 1 парк, но нет водоёмов.
data[columns][(data['city_centers_nearest'] > 18500) &
(data['city_centers_nearest'] < 18600) &
(data['airports_nearest'] > 19500) &
(data['airports_nearest'] < 19600) &
(data['parks_around_3000'] == 1) &
(data['ponds_around_3000'] == 0)] \
.sort_values('city_centers_nearest')
| floor | floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 12565 | 3 | 8.0 | Санкт-Петербург | 18525.0 | 19523.0 | 1.0 | 365.0 | 0.0 | 0.0 |
| 13989 | 2 | 8.0 | Санкт-Петербург | 18525.0 | 19523.0 | 1.0 | 365.0 | 0.0 | 0.0 |
| 22252 | 4 | 8.0 | Санкт-Петербург | 18525.0 | 19523.0 | 1.0 | 365.0 | 0.0 | 0.0 |
| 12399 | 4 | NaN | Санкт-Петербург | 18535.0 | 19533.0 | 1.0 | 375.0 | 0.0 | 0.0 |
| 3871 | 1 | 8.0 | Санкт-Петербург | 18583.0 | 19580.0 | 1.0 | 400.0 | 0.0 | 0.0 |
Заменим отсутствующие значения на значение 8.
data.loc[data['floors_total'].isna() &
(data['city_centers_nearest'] == 18535) &
(data['airports_nearest'] == 19533),
'floors_total'] = data['floors_total'].fillna(8)
data[columns][(data['city_centers_nearest'] == 18535) &
(data['airports_nearest'] == 19533)]
| floor | floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 12399 | 4 | 8.0 | Санкт-Петербург | 18535.0 | 19533.0 | 1.0 | 375.0 | 0.0 | 0.0 |
Выясним, какова этажность зданий в Мурино, расположенных от центра города на расстоянии 21 888 м и от аэропорта на расстоянии 51 553 м.
data[columns][(data['city_centers_nearest'] > 21000) &
(data['city_centers_nearest'] < 22500) &
(data['airports_nearest'] > 51000) &
(data['airports_nearest'] < 52000)] \
.sort_values('city_centers_nearest')
| floor | floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 10259 | 5 | NaN | Мурино | 21888.0 | 51553.0 | 0.0 | 0.0 | 2.0 | 133.0 |
| 11425 | 4 | NaN | Мурино | 21888.0 | 51553.0 | 0.0 | 0.0 | 2.0 | 133.0 |
В наборе данных нет сведений о рядом расположенных зданиях, поэтому заменим отсутствующие значения на максимальное значение признака floors — 5.
data.loc[(data['floors_total'].isna() == True) &
(data['city_centers_nearest'] == 21888) &
(data['airports_nearest'] == 51553),
'floors_total'] = data['floors_total'].fillna(5)
data[columns][(data['city_centers_nearest'] == 21888) &
(data['airports_nearest'] == 51553)]
| floor | floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 10259 | 5 | 5.0 | Мурино | 21888.0 | 51553.0 | 0.0 | 0.0 | 2.0 | 133.0 |
| 11425 | 4 | 5.0 | Мурино | 21888.0 | 51553.0 | 0.0 | 0.0 | 2.0 | 133.0 |
Выясним, какова этажность зданий в Красном Селе, расположенных от центра города на расстоянии 28 806 м и от аэропорта на расстоянии 25 382 м, вокруг которых нет парков и водоёмов.
data[columns][(data['city_centers_nearest'] > 28750) &
(data['city_centers_nearest'] < 28900) &
(data['airports_nearest'] > 25000) &
(data['airports_nearest'] < 25500) &
(data['parks_around_3000'] == 0)] \
.sort_values('city_centers_nearest')
| floor | floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 11488 | 1 | 8.0 | Красное Село | 28765.0 | 25341.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 2437 | 5 | 8.0 | Красное Село | 28784.0 | 25359.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 6789 | 3 | 8.0 | Красное Село | 28784.0 | 25359.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 15989 | 1 | NaN | Красное Село | 28806.0 | 25382.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 1976 | 7 | 9.0 | Красное Село | 28837.0 | 25413.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 11276 | 7 | 9.0 | Красное Село | 28837.0 | 25413.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 10352 | 3 | 8.0 | Красное Село | 28856.0 | 25431.0 | 0.0 | 0.0 | 0.0 | 0.0 |
Заменим отсутствующее значение на значение моды — 8.
data.loc[data['floors_total'].isna() &
(data['city_centers_nearest'] == 28806) &
(data['airports_nearest'] == 25382),
'floors_total'] = data['floors_total'].fillna(8)
data[columns][(data['city_centers_nearest'] == 28806) &
(data['airports_nearest'] == 25382)]
| floor | floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 15989 | 1 | 8.0 | Красное Село | 28806.0 | 25382.0 | 0.0 | 0.0 | 0.0 | 0.0 |
Выясним, какова этажность зданий в Пушкине, расположенных от центра города на расстоянии 31 813 м и от аэропорта на расстоянии 19 659 м.
data[columns][(data['city_centers_nearest'] > 31500) &
(data['city_centers_nearest'] < 32000) &
(data['airports_nearest'] > 19500) &
(data['airports_nearest'] < 20000) &
(data['locality_name'] == 'Пушкин')] \
.sort_values('city_centers_nearest')
| floor | floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 2526 | 4 | 5.0 | Пушкин | 31725.0 | 19571.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 8986 | 4 | NaN | Пушкин | 31813.0 | 19659.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 21119 | 2 | 4.0 | Пушкин | 31897.0 | 19744.0 | 0.0 | 0.0 | 0.0 | 0.0 |
| 17874 | 3 | 3.0 | Пушкин | 31914.0 | 19760.0 | 0.0 | 0.0 | 0.0 | 0.0 |
Поскольку все найденные значения разные, заполним отсутствующее значение медианным значением — 4.
data.loc[data['floors_total'].isna() &
(data['city_centers_nearest'] == 31813) &
(data['airports_nearest'] == 19659),
'floors_total'] = data['floors_total'].fillna(4)
data[columns][(data['city_centers_nearest'] == 31813) &
(data['airports_nearest'] == 19659)]
| floor | floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 8986 | 4 | 4.0 | Пушкин | 31813.0 | 19659.0 | 0.0 | 0.0 | 0.0 | 0.0 |
Выясним, какова этажность зданий в Щеглово, расположенных от центра города на расстоянии 34 085 м и от аэропорта на расстоянии 61 908 м.
data[columns][(data['city_centers_nearest'] > 33500) &
(data['city_centers_nearest'] < 34500) &
(data['airports_nearest'] > 61500) &
(data['airports_nearest'] < 62300)] \
.sort_values('city_centers_nearest')
| floor | floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 3817 | 1 | NaN | Щеглово | 34085.0 | 61908.0 | 0.0 | 0.0 | 0.0 | 0.0 |
В наборе данных нет сведений о рядом расположенных зданиях, поэтому заменим отсутствующее значение на моду значений этажности зданий, расположенных в Щеглово.
data.loc[data['locality_name'] == 'Щеглово', 'floors_total'].mode()
0 4.0 Name: floors_total, dtype: float64
Заменим отсутствующее значение на 4.
data.loc[data['floors_total'].isna() &
(data['city_centers_nearest'] == 34085) &
(data['airports_nearest'] == 61908),
'floors_total'] = data['floors_total'].fillna(4)
data[columns][(data['city_centers_nearest'] == 34085) &
(data['airports_nearest'] == 61908)]
| floor | floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 3817 | 1 | 4.0 | Щеглово | 34085.0 | 61908.0 | 0.0 | 0.0 | 0.0 | 0.0 |
Оставшиеся 10 записей, в которых отсутствует значение признака floors_total, не представляется возможным заполнить, поскольку в них наблюдается большое количество пропущенных значений, а из картографических данных имеется только название населённого пункта.
data[columns][data['floors_total'].isna()]
| floor | floors_total | locality_name | city_centers_nearest | airports_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | |
|---|---|---|---|---|---|---|---|---|---|
| 3031 | 12 | NaN | Кудрово | NaN | NaN | NaN | NaN | NaN | NaN |
| 3438 | 12 | NaN | Кудрово | NaN | NaN | NaN | NaN | NaN | NaN |
| 3831 | 7 | NaN | Санкт-Петербург | NaN | NaN | NaN | NaN | NaN | NaN |
| 4901 | 6 | NaN | Бугры | NaN | NaN | NaN | NaN | NaN | NaN |
| 5187 | 15 | NaN | Мурино | NaN | NaN | NaN | NaN | NaN | NaN |
| 9023 | 11 | NaN | Новоселье | NaN | NaN | NaN | NaN | NaN | NaN |
| 10058 | 21 | NaN | Шушары | NaN | NaN | NaN | NaN | NaN | NaN |
| 10351 | 4 | NaN | Токсово | NaN | NaN | NaN | NaN | NaN | NaN |
| 14094 | 17 | NaN | Новое Девяткино | NaN | NaN | NaN | NaN | NaN | NaN |
| 20738 | 10 | NaN | Мурино | NaN | NaN | NaN | NaN | NaN | NaN |
Поэтому эти записи необходимо удалить.
data.drop(index=data[data['floors_total'].isna()].index, inplace=True)
show_na()
| Всего пропусков | % | |
|---|---|---|
| ceiling_height | 9092 | 38.8 |
| ponds_nearest | 5421 | 23.1 |
| ponds_around_3000 | 5421 | 23.1 |
| parks_nearest | 5421 | 23.1 |
| parks_around_3000 | 5421 | 23.1 |
| city_centers_nearest | 5421 | 23.1 |
| airports_nearest | 5421 | 23.1 |
| days_exposition | 3153 | 13.4 |
| kitchen_area | 2254 | 9.6 |
| living_area | 1896 | 8.1 |
| total_images | 0 | 0.0 |
| balcony | 0 | 0.0 |
| locality_name | 0 | 0.0 |
| open_plan | 0 | 0.0 |
| last_price | 0 | 0.0 |
| studio | 0 | 0.0 |
| is_apartment | 0 | 0.0 |
| floor | 0 | 0.0 |
| floors_total | 0 | 0.0 |
| rooms | 0 | 0.0 |
| first_day_exposition | 0 | 0.0 |
| total_area | 0 | 0.0 |
| locality_type | 0 | 0.0 |
Почти 40 % значений признака ceiling_height содержат пропуски.
Поскольку большая часть зданий, в которых расположены объекты недвижимости, вероятно, представляют собой дома типовой застройки, высота потолков представляется такой же "типовой" величиной. На эти значения влияют толщина напольного и потолочного покрытий. Но, во-первых, далеко не во всех квартирах есть натяжной/подвесной потолок (сильно уменьшающий высоту потолков), а во-вторых, значение высоты потолка в объявлении могут указывать в соответствии с официальным планом квартиры, а не специально измеряют её для публикации объявления. Кроме того, можно полагать, что вероятность встретить в одном населённом пункте дома, принадлежащие к одному типу, выше, чем в разных населённых пунктах. Таким образом, наличие популярного значения (моды) в значении высоты потолка для зданий определённой этажности в каждом населённом пункте может расцениваться как типовое значение высоты потолка.
Поэтому будем заполнять пропуски модой, рассчитанной для зданий определённой этажности в каждом населённом пункте. В случае, когда в выборках присутствует более одной моды, будем заполнять пропуски медианным значением, которое зачастую расположено между значениями мод, и таким образом является средним ещё и для мод.
for locality in list(data.loc[data['ceiling_height'].isna(),
'locality_name'].unique()):
for floors in list(data.loc[data['ceiling_height'].isna() &
(data['locality_name'] == locality),
'floors_total'].unique()):
mode_value = data[data['ceiling_height'].notna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors)]['ceiling_height'].mode()
median_value = data[data['ceiling_height'].notna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors)]['ceiling_height'].median()
if len(mode_value) == 1:
data.loc[data['ceiling_height'].isna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors),
'ceiling_height'] = mode_value[0]
elif len(mode_value) != 1:
data.loc[data['ceiling_height'].isna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors),
'ceiling_height'] = median_value
data['ceiling_height'].sort_values().unique()
array([2. , 2.25 , 2.26 , 2.3 , 2.34 , 2.4 , 2.45 , 2.46 , 2.47 ,
2.48 , 2.49 , 2.5 , 2.51 , 2.52 , 2.525, 2.53 , 2.54 , 2.55 ,
2.56 , 2.57 , 2.575, 2.58 , 2.59 , 2.6 , 2.61 , 2.615, 2.62 ,
2.625, 2.63 , 2.64 , 2.65 , 2.65 , 2.66 , 2.67 , 2.675, 2.68 ,
2.69 , 2.7 , 2.71 , 2.72 , 2.725, 2.73 , 2.74 , 2.75 , 2.76 ,
2.77 , 2.775, 2.775, 2.78 , 2.79 , 2.8 , 2.81 , 2.82 , 2.83 ,
2.84 , 2.85 , 2.86 , 2.87 , 2.88 , 2.89 , 2.9 , 2.91 , 2.92 ,
2.93 , 2.94 , 2.95 , 2.96 , 2.97 , 2.98 , 2.99 , 3. , 3.01 ,
3.02 , 3.03 , 3.04 , 3.05 , 3.06 , 3.07 , 3.08 , 3.09 , 3.1 ,
3.11 , 3.12 , 3.13 , 3.14 , 3.15 , 3.16 , 3.17 , 3.18 , 3.2 ,
3.21 , 3.22 , 3.23 , 3.24 , 3.25 , 3.26 , 3.27 , 3.28 , 3.29 ,
3.3 , 3.31 , 3.32 , 3.325, 3.33 , 3.34 , 3.35 , 3.36 , 3.37 ,
3.38 , 3.39 , 3.4 , 3.42 , 3.43 , 3.44 , 3.45 , 3.46 , 3.47 ,
3.48 , 3.49 , 3.5 , 3.51 , 3.52 , 3.53 , 3.54 , 3.55 , 3.56 ,
3.57 , 3.58 , 3.59 , 3.6 , 3.62 , 3.63 , 3.65 , 3.66 , 3.67 ,
3.68 , 3.69 , 3.7 , 3.75 , 3.76 , 3.78 , 3.8 , 3.82 , 3.83 ,
3.84 , 3.85 , 3.86 , 3.87 , 3.88 , 3.9 , 3.93 , 3.95 , 3.98 ,
4. , 4.06 , 4.1 , 4.14 , 4.15 , 4.19 , 4.2 , 4.25 , 4.3 ,
4.37 , 4.4 , 4.45 , 4.5 , 4.65 , 4.7 , 4.8 , 4.9 , 5. ,
5.2 , 5.3 , 5.5 , 5.6 , 5.8 , 6. , nan])
Выясним, сколько осталось записей, содержащих пропуски в значениях признака ceiling_height.
data['ceiling_height'].isna().sum()
314
Среди записей, в которых отсутствует значение высоты потолка, нет объектов недвижимости, расположенных в Санкт-Петербурге.
len(data[data['ceiling_height'].isna() &
(data['locality_name'] == 'Санкт-Петербург')])
0
Распределение значений высоты потолка объектов недвижимости, расположенных в Санкт-Петербурге, отличается от распределения значений высоты потолка объектов недвижимости в Ленинградской области. Отличаются и значения мод. Вероятно, такое распределение величины является следствием того, что область преимущественно застраивалась типовыми зданиями, а в Санкт-Петербурге расположено большое количество зданий более ранней постройки.
Поэтому заполним отсутствующие значения модой, рассчитанной для зданий определённой этажности, расположенных в Ленинградской области. А в случае, если таких мод несколько, то медианным значением.
for floors in list(data.loc[data['ceiling_height'].isna() &
(data['locality_name'] != 'Санкт-Петербург'),
'floors_total'].unique()):
mode_value = data[data['ceiling_height'].notna() &
(data['floors_total'] == floors)]['ceiling_height'].mode()
median_value = data[data['ceiling_height'].notna() &
(data['floors_total'] == floors)]['ceiling_height'].median()
if len(mode_value) == 1:
data.loc[data['ceiling_height'].isna() &
(data['floors_total'] == floors),
'ceiling_height'] = mode_value[0]
elif len(mode_value) != 1:
data.loc[data['ceiling_height'].isna() &
(data['floors_total'] == floors),
'ceiling_height'] = median_value
data['ceiling_height'].sort_values().unique()
array([2. , 2.25 , 2.26 , 2.3 , 2.34 , 2.4 , 2.45 , 2.46 , 2.47 ,
2.48 , 2.49 , 2.5 , 2.51 , 2.52 , 2.525, 2.53 , 2.54 , 2.55 ,
2.56 , 2.57 , 2.575, 2.58 , 2.59 , 2.6 , 2.61 , 2.615, 2.62 ,
2.625, 2.63 , 2.64 , 2.65 , 2.65 , 2.66 , 2.67 , 2.675, 2.68 ,
2.69 , 2.7 , 2.71 , 2.72 , 2.725, 2.73 , 2.74 , 2.75 , 2.76 ,
2.77 , 2.775, 2.775, 2.78 , 2.79 , 2.8 , 2.81 , 2.82 , 2.83 ,
2.84 , 2.85 , 2.86 , 2.87 , 2.88 , 2.89 , 2.9 , 2.91 , 2.92 ,
2.93 , 2.94 , 2.95 , 2.96 , 2.97 , 2.98 , 2.99 , 3. , 3.01 ,
3.02 , 3.03 , 3.04 , 3.05 , 3.06 , 3.07 , 3.08 , 3.09 , 3.1 ,
3.11 , 3.12 , 3.13 , 3.14 , 3.15 , 3.16 , 3.17 , 3.18 , 3.2 ,
3.21 , 3.22 , 3.23 , 3.24 , 3.25 , 3.26 , 3.27 , 3.28 , 3.29 ,
3.3 , 3.31 , 3.32 , 3.325, 3.33 , 3.34 , 3.35 , 3.36 , 3.37 ,
3.38 , 3.39 , 3.4 , 3.42 , 3.43 , 3.44 , 3.45 , 3.46 , 3.47 ,
3.48 , 3.49 , 3.5 , 3.51 , 3.52 , 3.53 , 3.54 , 3.55 , 3.56 ,
3.57 , 3.58 , 3.59 , 3.6 , 3.62 , 3.63 , 3.65 , 3.66 , 3.67 ,
3.68 , 3.69 , 3.7 , 3.75 , 3.76 , 3.78 , 3.8 , 3.82 , 3.83 ,
3.84 , 3.85 , 3.86 , 3.87 , 3.88 , 3.9 , 3.93 , 3.95 , 3.98 ,
4. , 4.06 , 4.1 , 4.14 , 4.15 , 4.19 , 4.2 , 4.25 , 4.3 ,
4.37 , 4.4 , 4.45 , 4.5 , 4.65 , 4.7 , 4.8 , 4.9 , 5. ,
5.2 , 5.3 , 5.5 , 5.6 , 5.8 , 6. ])
Все значения высоты потолков расположены в установленном диапазоне 2—6 м. Пропуски все заполнены.
show_na()
| Всего пропусков | % | |
|---|---|---|
| ponds_nearest | 5421 | 23.1 |
| ponds_around_3000 | 5421 | 23.1 |
| parks_nearest | 5421 | 23.1 |
| parks_around_3000 | 5421 | 23.1 |
| city_centers_nearest | 5421 | 23.1 |
| airports_nearest | 5421 | 23.1 |
| days_exposition | 3153 | 13.4 |
| kitchen_area | 2254 | 9.6 |
| living_area | 1896 | 8.1 |
| total_images | 0 | 0.0 |
| locality_name | 0 | 0.0 |
| balcony | 0 | 0.0 |
| open_plan | 0 | 0.0 |
| last_price | 0 | 0.0 |
| studio | 0 | 0.0 |
| is_apartment | 0 | 0.0 |
| floor | 0 | 0.0 |
| floors_total | 0 | 0.0 |
| ceiling_height | 0 | 0.0 |
| rooms | 0 | 0.0 |
| first_day_exposition | 0 | 0.0 |
| total_area | 0 | 0.0 |
| locality_type | 0 | 0.0 |
Поскольку опубликованные в объявлениях значения высоты потолка были определены с точностью до 0,01 м, то все рассчитанные значения должны быть округлены с точностью до 0,01 м.
data['ceiling_height'] = data['ceiling_height'].round(2)
data['ceiling_height'].sort_values().unique()
array([2. , 2.25, 2.26, 2.3 , 2.34, 2.4 , 2.45, 2.46, 2.47, 2.48, 2.49,
2.5 , 2.51, 2.52, 2.53, 2.54, 2.55, 2.56, 2.57, 2.58, 2.59, 2.6 ,
2.61, 2.62, 2.63, 2.64, 2.65, 2.66, 2.67, 2.68, 2.69, 2.7 , 2.71,
2.72, 2.73, 2.74, 2.75, 2.76, 2.77, 2.78, 2.79, 2.8 , 2.81, 2.82,
2.83, 2.84, 2.85, 2.86, 2.87, 2.88, 2.89, 2.9 , 2.91, 2.92, 2.93,
2.94, 2.95, 2.96, 2.97, 2.98, 2.99, 3. , 3.01, 3.02, 3.03, 3.04,
3.05, 3.06, 3.07, 3.08, 3.09, 3.1 , 3.11, 3.12, 3.13, 3.14, 3.15,
3.16, 3.17, 3.18, 3.2 , 3.21, 3.22, 3.23, 3.24, 3.25, 3.26, 3.27,
3.28, 3.29, 3.3 , 3.31, 3.32, 3.33, 3.34, 3.35, 3.36, 3.37, 3.38,
3.39, 3.4 , 3.42, 3.43, 3.44, 3.45, 3.46, 3.47, 3.48, 3.49, 3.5 ,
3.51, 3.52, 3.53, 3.54, 3.55, 3.56, 3.57, 3.58, 3.59, 3.6 , 3.62,
3.63, 3.65, 3.66, 3.67, 3.68, 3.69, 3.7 , 3.75, 3.76, 3.78, 3.8 ,
3.82, 3.83, 3.84, 3.85, 3.86, 3.87, 3.88, 3.9 , 3.93, 3.95, 3.98,
4. , 4.06, 4.1 , 4.14, 4.15, 4.19, 4.2 , 4.25, 4.3 , 4.37, 4.4 ,
4.45, 4.5 , 4.65, 4.7 , 4.8 , 4.9 , 5. , 5.2 , 5.3 , 5.5 , 5.6 ,
5.8 , 6. ])
Всего записей о квартирах-студиях с пропущенным значением жилой площади — 13.
len(data[data['studio'] & data['living_area'].isna()])
13
Заполним пропущенное значение жилой площади средним арифметическим значением, рассчитанным для квартир-студий в каждом населённом пункте, каждого здания определённой этажности и каждой квартиры с определённым числом жилых комнат.
for locality in list(data.loc[data['studio'] &
data['living_area'].isna(),
'locality_name'].sort_values().unique()):
for floors in list(data.loc[data['studio'] &
data['living_area'].isna() &
(data['locality_name'] == locality),
'floors_total'].sort_values().unique()):
for rooms in list(data.loc[data['studio'] &
data['living_area'].isna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors),
'rooms'].sort_values().unique()):
mean_value = data.loc[data['studio'] &
data['living_area'].notna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'living_area'].mean()
data.loc[data['studio'] &
data['living_area'].isna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'living_area'] = mean_value
Количество записей, для которых не удалось рассчитать среднее значение жилой площади.
len(data[data['studio'] & data['living_area'].isna()])
5
Заполним пропущенное значение жилой площади средним арифметическим значением, рассчитанным для квартир-студий во всех населённых пунктах, для каждого здания определённой этажности и каждой квартиры с определённым числом жилых комнат.
for floors in list(data.loc[data['studio'] &
data['living_area'].isna(),
'floors_total'].sort_values().unique()):
for rooms in list(data.loc[data['studio'] &
data['living_area'].isna() &
(data['floors_total'] == floors),
'rooms'].sort_values().unique()):
mean_value = data.loc[data['studio'] &
data['living_area'].notna() &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'living_area'].mean()
data.loc[data['studio'] &
data['living_area'].isna() &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'living_area'] = mean_value
Количество записей, для которых не удалось рассчитать среднее значение жилой площади.
len(data[data['studio'] & data['living_area'].isna()])
2
Заполним пропущенное значение жилой площади средним арифметическим значением, рассчитанным для квартир-студий во всех населённых пунктах, в зданиях любой этажности, но для каждой квартиры с определённым числом жилых комнат.
for rooms in list(data.loc[data['studio'] &
data['living_area'].isna(),
'rooms'].sort_values().unique()):
mean_value = data.loc[data['living_area'].notna() &
(data['rooms'] == rooms), 'living_area'].mean()
data.loc[data['studio'] &
data['living_area'].isna() &
(data['rooms'] == rooms), 'living_area'] = mean_value
Количество записей, не удовлетворяющих критерию, что минимальная площадь, приходящаяся на вспомогательные помещения (кроме кухни) составляет 2 м².
len(data[data['total_area'] < data['living_area'] + 2])
0
Всего записей о квартирах-студиях с пропущенным значением площади кухни — 211.
len(data[data['studio'] & data['kitchen_area'].isna()])
211
Поскольку в таких квартирах часто кухня выполнена в виде кухни-нишы, а однокомнатных квартир-студий — подавляющее количество среди всех студий, будем полагать, что площадь, отводимая на зону кухни-ниши, составляет 15 % от общей площади. Тем более, что это близко к среднему значению по всему набору данных — 19 % от общей площади приходится на площадь кухни.
(data['kitchen_area']/data['total_area']).mean().round(2)
0.19
data.loc[data['studio'], 'kitchen_area'] = 0.15 * data['total_area']
show_na()
| Всего пропусков | % | |
|---|---|---|
| ponds_nearest | 5421 | 23.1 |
| ponds_around_3000 | 5421 | 23.1 |
| parks_nearest | 5421 | 23.1 |
| parks_around_3000 | 5421 | 23.1 |
| city_centers_nearest | 5421 | 23.1 |
| airports_nearest | 5421 | 23.1 |
| days_exposition | 3153 | 13.4 |
| kitchen_area | 2043 | 8.7 |
| living_area | 1883 | 8.0 |
| total_images | 0 | 0.0 |
| locality_name | 0 | 0.0 |
| balcony | 0 | 0.0 |
| open_plan | 0 | 0.0 |
| last_price | 0 | 0.0 |
| studio | 0 | 0.0 |
| is_apartment | 0 | 0.0 |
| floor | 0 | 0.0 |
| floors_total | 0 | 0.0 |
| ceiling_height | 0 | 0.0 |
| rooms | 0 | 0.0 |
| first_day_exposition | 0 | 0.0 |
| total_area | 0 | 0.0 |
| locality_type | 0 | 0.0 |
Пропущенных значений признака kitchen_area больше, чем признака living_area. Количество пропусков приблизительно равно 10 % в каждом признаке.
Количество записей, в которых указана жилая площадь, но не указана площадь кухни — 599.
len(data[~data['studio'] &
data['living_area'].notna() &
data['kitchen_area'].isna()])
599
Все эти объекты недвижимости расположены в 59 различных населённых пунктах.
len(data.loc[~data['studio'] &
data['living_area'].notna() &
data['kitchen_area'].isna(), 'locality_name'].unique())
59
Поскольку значение площади кухни есть величина непрерывная и вариативная, в качестве оценки среднего значения примем среднее арифметическое. В каждом населённом пункте для домов определённой этажности рассчитаем среднее значение площади кухни для каждого типа квартир (1-комн., 2-комн. и т. д.). Заполним отсутствующие значения площади кухни средним арифметическим, рассчитанным в соответствии с количеством комнат в квартире, этажностью здания, в котором располагается объект недвижимости, и населённым пунктом, где располагается здание.
for locality in list(data.loc[~data['studio'] &
data['kitchen_area'].isna() &
data['living_area'].notna(),
'locality_name'].sort_values().unique()):
for floors in list(data.loc[~data['studio'] &
data['kitchen_area'].isna() &
data['living_area'].notna() &
(data['locality_name'] == locality),
'floors_total'].sort_values().unique()):
for rooms in list(data.loc[~data['studio'] &
data['kitchen_area'].isna() &
data['living_area'].notna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors),
'rooms'].sort_values().unique()):
mean_value = data.loc[~data['studio'] &
data['kitchen_area'].notna() &
data['living_area'].notna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors) &
(data['rooms'] == rooms),
'kitchen_area'].mean()
data.loc[~data['studio'] &
data['kitchen_area'].isna() &
data['living_area'].notna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'kitchen_area'] = mean_value
Количество записей, для которых не удалось рассчитать среднее значение площади кухни.
len(data[~data['studio'] &
data['living_area'].notna() &
data['kitchen_area'].isna()])
19
Количество записей, для которых не выполняется критерий, что площадь вспомогательных помещений (кроме кухни) должна составлять не менее 2 м².
len(data[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2)])
161
Заменим в таких записях полученное значение площади кухни значением NaN.
data.loc[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2),
'kitchen_area'] = 0
data['kitchen_area'].replace(0, np.nan, inplace=True)
len(data[~data['studio'] &
data['living_area'].notna() &
data['kitchen_area'].isna()])
180
Рассчитаем теперь для каждого населенного пункта минимальное значение площади кухни для схожих объектов недвижимости: расположенных в квартирах такой же комнатности, зданиях такой же этажности, в том же населённом пункте.
for locality in list(data.loc[~data['studio'] &
data['kitchen_area'].isna() &
data['living_area'].notna(),
'locality_name'].sort_values().unique()):
for floors in list(data.loc[~data['studio'] &
data['kitchen_area'].isna() &
data['living_area'].notna() &
(data['locality_name'] == locality),
'floors_total'].sort_values().unique()):
for rooms in list(data.loc[~data['studio'] &
data['kitchen_area'].isna() &
data['living_area'].notna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors),
'rooms'].sort_values().unique()):
min_value = data.loc[~data['studio'] &
data['kitchen_area'].notna() &
data['living_area'].notna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'kitchen_area'].min()
data.loc[~data['studio'] &
data['kitchen_area'].isna() &
data['living_area'].notna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'kitchen_area'] = min_value
Теперь количество записей, не удовлетворяющих критерию, уменьшилось.
len(data[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2)])
75
Заменим в таких записях полученное значение площади кухни значением NaN.
data.loc[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2),
'kitchen_area'] = 0
data['kitchen_area'].replace(0, np.nan, inplace=True)
len(data[~data['studio'] &
data['living_area'].notna() &
data['kitchen_area'].isna()])
94
Теперь рассчитаем среднее арифметическое по региону для квартир той же комнатности и зданий той же этажности.
for floors in list(data.loc[~data['studio'] &
data['kitchen_area'].isna() &
data['living_area'].notna(),
'floors_total'].sort_values().unique()):
for rooms in list(data.loc[~data['studio'] &
data['kitchen_area'].isna() &
data['living_area'].notna() &
(data['floors_total'] == floors),
'rooms'].sort_values().unique()):
mean_value = data.loc[~data['studio'] &
data['kitchen_area'].notna() &
data['living_area'].notna() &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'kitchen_area'].mean()
data.loc[~data['studio'] &
data['kitchen_area'].isna() &
data['living_area'].notna() &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'kitchen_area'] = mean_value
Количество записей, для которых не удалось произвести заполнение средним значением площади кухни.
len(data[~data['studio'] &
data['living_area'].notna() &
data['kitchen_area'].isna()])
1
Количество записей, для которых не выполнен критерий, что площадь вспомогательных помещений (кроме кухни) должна составлять не менее 2 м².
len(data[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2)])
77
Заменим в таких записях полученное значение площади кухни значением NaN.
data.loc[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2),
'kitchen_area'] = 0
data['kitchen_area'].replace(0, np.nan, inplace=True)
len(data[~data['studio'] &
data['living_area'].notna() &
data['kitchen_area'].isna()])
78
Теперь рассчитаем минимальное значение по региону для квартир той же комнатности и зданий той же этажности.
for floors in list(data.loc[~data['studio'] &
data['kitchen_area'].isna() &
data['living_area'].notna(),
'floors_total'].sort_values().unique()):
for rooms in list(data.loc[~data['studio'] &
data['kitchen_area'].isna() &
data['living_area'].notna() &
(data['floors_total'] == floors),
'rooms'].sort_values().unique()):
min_value = data.loc[~data['studio'] &
data['kitchen_area'].notna() &
data['living_area'].notna() &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'kitchen_area'].min()
data.loc[~data['studio'] &
data['kitchen_area'].isna() &
data['living_area'].notna() &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'kitchen_area'] = min_value
Количество записей, для которых не выполнен критерий, что площадь вспомогательных помещений (кроме кухни) должна составлять не менее 2 м².
len(data[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2)])
34
Заменим в таких записях полученное значение площади кухни значением NaN.
data.loc[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2),
'kitchen_area'] = 0
data['kitchen_area'].replace(0, np.nan, inplace=True)
len(data[~data['studio'] &
data['living_area'].notna() &
data['kitchen_area'].isna()])
35
Теперь рассчитаем среднее по региону для зданий любой этажности, но для квартир той же комнатности.
for rooms in list(data.loc[~data['studio'] &
data['kitchen_area'].isna() &
data['living_area'].notna(),
'rooms'].sort_values().unique()):
mean_value = data.loc[~data['studio'] &
data['kitchen_area'].notna() &
data['living_area'].notna() &
(data['rooms'] == rooms), 'kitchen_area'].mean()
data.loc[~data['studio'] &
data['kitchen_area'].isna() &
data['living_area'].notna() &
(data['rooms'] == rooms), 'kitchen_area'] = mean_value
Удалось заполнить значения для всех записей, в которых пропущено значение площади кухни, но имеется значение жилой площади.
len(data[~data['studio'] &
data['living_area'].notna() & data['kitchen_area'].isna()])
0
Однако не для всех записей выполняется критерий, что площадь вспомогательных помещений (кроме кухни) должна составлять не менее 2 м².
len(data[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2)])
34
Заменим в таких записях полученное значение площади кухни значением NaN.
data.loc[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2),
'kitchen_area'] = 0
data['kitchen_area'].replace(0, np.nan, inplace=True)
len(data[~data['studio'] &
data['living_area'].notna() & data['kitchen_area'].isna()])
34
Теперь рассчитаем минимальное значение по региону для зданий любой этажностей, но для квартир той же комнатности.
for rooms in list(data.loc[~data['studio'] &
data['kitchen_area'].isna() &
data['living_area'].notna(),
'rooms'].sort_values().unique()):
min_value = data.loc[~data['studio'] &
data['kitchen_area'].notna() &
data['living_area'].notna() &
(data['rooms'] == rooms), 'kitchen_area'].min()
data.loc[~data['studio'] &
data['kitchen_area'].isna() &
data['living_area'].notna() &
(data['rooms'] == rooms), 'kitchen_area'] = min_value
Убедимся, что критерий (площадь вспомогательных помещений (кроме кухни) должна составлять не менее 2 м²) выполняется для всех записей.
len(data[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2)])
0
Количество записей, в которых указана площадь кухни, но не указана жилая площадь.
len(data[~data['studio'] &
data['living_area'].isna() &
data['kitchen_area'].notna()])
439
Все эти объекты недвижимости расположены в 53 различных населённых пунктах.
len(data.loc[~data['studio'] &
data['living_area'].isna() &
data['kitchen_area'].notna(), 'locality_name'].unique())
53
Заполним средним арифметическим значением жилой площади, рассчитанным по известным значениям жилой площади объектов, расположенных в тех же населённых пунктах, в зданиях той же этажности и с тем же количеством жилых комнат.
for locality in list(data.loc[~data['studio'] &
data['kitchen_area'].notna() &
data['living_area'].isna(),
'locality_name'].sort_values().unique()):
for floors in list(data.loc[~data['studio'] &
data['kitchen_area'].notna() &
data['living_area'].isna() &
(data['locality_name'] == locality),
'floors_total'].sort_values().unique()):
for rooms in list(data.loc[~data['studio'] &
data['kitchen_area'].notna() &
data['living_area'].isna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors),
'rooms'].sort_values().unique()):
mean_value = data.loc[~data['studio'] &
data['kitchen_area'].notna() &
data['living_area'].notna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'living_area'].mean()
data.loc[~data['studio'] &
data['kitchen_area'].notna() &
data['living_area'].isna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'living_area'] = mean_value
Количество записей, для которых не удалось рассчитать среднее значение жилой площади.
len(data[~data['studio'] &
data['living_area'].isna() &
data['kitchen_area'].notna()])
34
Количество записей, для которых не выполняется критерий, что площадь вспомогательных помещений (кроме кухни) должна составлять не менее 2 м².
len(data[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2)])
19
Заменим в таких записях полученное значение жилой площади значением NaN.
data.loc[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2),
'living_area'] = 0
data['living_area'].replace(0, np.nan, inplace=True)
len(data[~data['studio'] &
data['living_area'].isna() &
data['kitchen_area'].notna()])
53
Заполним минимальным значением жилой площади, рассчитанным по известным значениям жилой площади объектов, расположенных в тех же населённых пунктах, в зданиях той же этажности и с тем же количеством жилых комнат.
for locality in list(data.loc[~data['studio'] &
data['kitchen_area'].notna() &
data['living_area'].isna(),
'locality_name'].sort_values().unique()):
for floors in list(data.loc[~data['studio'] &
data['kitchen_area'].notna() &
data['living_area'].isna() &
(data['locality_name'] == locality),
'floors_total'].sort_values().unique()):
for rooms in list(data.loc[~data['studio'] &
data['kitchen_area'].notna() &
data['living_area'].isna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors),
'rooms'].sort_values().unique()):
min_value = data.loc[~data['studio'] &
data['kitchen_area'].notna() &
data['living_area'].notna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'living_area'].min()
data.loc[~data['studio'] &
data['kitchen_area'].notna() &
data['living_area'].isna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'living_area'] = min_value
Количество записей, для которых не выполняется критерий, что площадь вспомогательных помещений (кроме кухни) должна составлять не менее 2 м².
len(data[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2)])
5
Заменим в таких записях полученное значение жилой площади значением NaN.
data.loc[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2),
'living_area'] = 0
data['living_area'].replace(0, np.nan, inplace=True)
len(data[~data['studio'] &
data['living_area'].isna() &
data['kitchen_area'].notna()])
39
Заполним средним арифметическим значением жилой площади, рассчитанным по известным значениям жилой площади объектов, расположенных во всех населённых пунктах, но в зданиях той же этажности и с тем же количеством жилых комнат.
for floors in list(data.loc[~data['studio'] &
data['kitchen_area'].notna() &
data['living_area'].isna(),
'floors_total'].sort_values().unique()):
for rooms in list(data.loc[~data['studio'] &
data['kitchen_area'].notna() &
data['living_area'].isna() &
(data['floors_total'] == floors),
'rooms'].sort_values().unique()):
mean_value = data.loc[~data['studio'] &
data['kitchen_area'].notna() &
data['living_area'].notna() &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'living_area'].mean()
data.loc[~data['studio'] &
data['kitchen_area'].notna() &
data['living_area'].isna() &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'living_area'] = mean_value
Количество записей, для которых не удалось рассчитать среднее значение жилой площади.
len(data[~data['studio'] &
data['living_area'].isna() & data['kitchen_area'].notna()])
0
Количество записей, для которых не выполняется критерий, что площадь вспомогательных помещений (кроме кухни) должна составлять не менее 2 м².
len(data[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2)])
6
Заменим в таких записях полученное значение жилой площади значением NaN.
data.loc[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2),
'living_area'] = 0
data['living_area'].replace(0, np.nan, inplace=True)
len(data[~data['studio'] &
data['living_area'].isna() &
data['kitchen_area'].notna()])
6
Заполним минимальным значением жилой площади, рассчитанным по известным значениям жилой площади объектов, расположенных во всех населённых пунктах, но в зданиях той же этажности и с тем же количеством жилых комнат.
for floors in list(data.loc[~data['studio'] &
data['kitchen_area'].notna() &
data['living_area'].isna(),
'floors_total'].sort_values().unique()):
for rooms in list(data.loc[~data['studio'] &
data['kitchen_area'].notna() &
data['living_area'].isna() &
(data['floors_total'] == floors),
'rooms'].sort_values().unique()):
min_value = data.loc[~data['studio'] &
data['kitchen_area'].notna() &
data['living_area'].notna() &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'living_area'].min()
data.loc[~data['studio'] &
data['kitchen_area'].notna() &
data['living_area'].isna() &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'living_area'] = min_value
Количество записей, для которых не выполняется критерий, что площадь вспомогательных помещений (кроме кухни) должна составлять не менее 2 м².
len(data[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2)])
0
show_na()
| Всего пропусков | % | |
|---|---|---|
| ponds_nearest | 5421 | 23.1 |
| ponds_around_3000 | 5421 | 23.1 |
| parks_nearest | 5421 | 23.1 |
| parks_around_3000 | 5421 | 23.1 |
| city_centers_nearest | 5421 | 23.1 |
| airports_nearest | 5421 | 23.1 |
| days_exposition | 3153 | 13.4 |
| kitchen_area | 1444 | 6.2 |
| living_area | 1444 | 6.2 |
| total_images | 0 | 0.0 |
| locality_name | 0 | 0.0 |
| balcony | 0 | 0.0 |
| open_plan | 0 | 0.0 |
| last_price | 0 | 0.0 |
| studio | 0 | 0.0 |
| is_apartment | 0 | 0.0 |
| floor | 0 | 0.0 |
| floors_total | 0 | 0.0 |
| ceiling_height | 0 | 0.0 |
| rooms | 0 | 0.0 |
| first_day_exposition | 0 | 0.0 |
| total_area | 0 | 0.0 |
| locality_type | 0 | 0.0 |
Количество записей, в которых не указана жилая площадь и не указана площадь кухни.
len(data[~data['studio'] &
data['living_area'].isna() &
data['kitchen_area'].isna()])
1444
Заполним средним арифметическим значением жилой площади, рассчитанным по известным значениям жилой площади объектов, расположенных в тех же населённых пунктах, в зданиях той же этажности и с тем же количеством жилых комнат.
То же самое выполняем и для значений площади кухни.
for locality in list(data.loc[~data['studio'] &
data['living_area'].isna(),
'locality_name'].sort_values().unique()):
for floors in list(data.loc[~data['studio'] &
data['living_area'].isna() &
(data['locality_name'] == locality),
'floors_total'].sort_values().unique()):
for rooms in list(data.loc[~data['studio'] &
data['living_area'].isna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors),
'rooms'].sort_values().unique()):
mean_value = data.loc[~data['studio'] &
data['living_area'].notna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'living_area'].mean()
data.loc[~data['studio'] &
data['living_area'].isna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'living_area'] = mean_value
for locality in list(data.loc[~data['studio'] &
data['kitchen_area'].isna(),
'locality_name'].sort_values().unique()):
for floors in list(data.loc[~data['studio'] &
data['kitchen_area'].isna() &
(data['locality_name'] == locality),
'floors_total'].sort_values().unique()):
for rooms in list(data.loc[~data['studio'] &
data['kitchen_area'].isna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors),
'rooms'].sort_values().unique()):
mean_value = data.loc[~data['studio'] &
data['kitchen_area'].notna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'kitchen_area'].mean()
data.loc[~data['studio'] &
data['kitchen_area'].isna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'kitchen_area'] = mean_value
Количество записей, для которых не удалось рассчитать среднее значение жилой площади.
len(data[~data['studio'] &
data['living_area'].isna() & data['kitchen_area'].isna()])
103
Количество записей, для которых не выполняется критерий, что площадь вспомогательных помещений (кроме кухни) должна составлять не менее 2 м².
len(data[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2)])
146
Заменим в таких записях полученное значение жилой площади и значение площади кухни значением NaN.
data.loc[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2),
'living_area'] = 0
data.loc[data['living_area'] == 0, 'kitchen_area'] = 0
data['living_area'].replace(0, np.nan, inplace=True)
data['kitchen_area'].replace(0, np.nan, inplace=True)
len(data[~data['studio'] &
data['living_area'].isna() & data['kitchen_area'].isna()])
249
Заполним минимальным значением жилой площади, рассчитанным по известным значениям жилой площади объектов, расположенных в тех же населённых пунктах, в зданиях той же этажности и с тем же количеством жилых комнат.
То же самое выполняем и для значений площади кухни.
for locality in list(data.loc[~data['studio'] &
data['living_area'].isna(),
'locality_name'].sort_values().unique()):
for floors in list(data.loc[~data['studio'] &
data['living_area'].isna() &
(data['locality_name'] == locality),
'floors_total'].sort_values().unique()):
for rooms in list(data.loc[~data['studio'] &
data['living_area'].isna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors),
'rooms'].sort_values().unique()):
min_value = data.loc[~data['studio'] &
data['living_area'].notna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'living_area'].min()
data.loc[~data['studio'] &
data['living_area'].isna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'living_area'] = min_value
for locality in list(data.loc[~data['studio'] &
data['kitchen_area'].isna(),
'locality_name'].sort_values().unique()):
for floors in list(data.loc[~data['studio'] &
data['kitchen_area'].isna() &
(data['locality_name'] == locality),
'floors_total'].sort_values().unique()):
for rooms in list(data.loc[~data['studio'] &
data['kitchen_area'].isna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors),
'rooms'].sort_values().unique()):
min_value = data.loc[~data['studio'] &
data['kitchen_area'].notna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'kitchen_area'].min()
data.loc[~data['studio'] &
data['kitchen_area'].isna() &
(data['locality_name'] == locality) &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'kitchen_area'] = min_value
Количество записей, для которых не выполняется критерий, что площадь вспомогательных помещений (кроме кухни) должна составлять не менее 2 м².
len(data[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2)])
15
Заменим в таких записях полученное значение жилой площади и значение площади кухни значением NaN.
data.loc[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2),
'living_area'] = 0
data.loc[data['living_area'] == 0, 'kitchen_area'] = 0
data['living_area'].replace(0, np.nan, inplace=True)
data['kitchen_area'].replace(0, np.nan, inplace=True)
len(data[~data['studio'] &
data['living_area'].isna() & data['kitchen_area'].isna()])
118
Заполним средним арифметическим значением жилой площади, рассчитанным по известным значениям жилой площади объектов, расположенных во всех населённых пунктах, но в зданиях той же этажности и с тем же количеством жилых комнат.
То же самое выполняем и для значений площади кухни.
for floors in list(data.loc[~data['studio'] &
data['living_area'].isna(),
'floors_total'].sort_values().unique()):
for rooms in list(data.loc[~data['studio'] &
data['living_area'].isna() &
(data['floors_total'] == floors),
'rooms'].sort_values().unique()):
mean_value = data.loc[~data['studio'] &
data['living_area'].notna() &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'living_area'].mean()
data.loc[~data['studio'] &
data['living_area'].isna() &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'living_area'] = mean_value
for floors in list(data.loc[~data['studio'] &
data['kitchen_area'].isna(),
'floors_total'].sort_values().unique()):
for rooms in list(data.loc[~data['studio'] &
data['kitchen_area'].isna() &
(data['floors_total'] == floors),
'rooms'].sort_values().unique()):
mean_value = data.loc[~data['studio'] &
data['kitchen_area'].notna() &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'kitchen_area'].mean()
data.loc[~data['studio'] &
data['kitchen_area'].isna() &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'kitchen_area'] = mean_value
Количество записей, для которых не удалось рассчитать среднее значение жилой площади.
len(data[~data['studio'] &
data['living_area'].isna() & data['kitchen_area'].isna()])
3
Количество записей, для которых не выполняется критерий, что площадь вспомогательных помещений (кроме кухни) должна составлять не менее 2 м².
len(data[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2)])
35
Заменим в таких записях полученное значение жилой площади и значение площади кухни значением NaN.
data.loc[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2),
'living_area'] = 0
data.loc[data['living_area'] == 0, 'kitchen_area'] = 0
data['living_area'].replace(0, np.nan, inplace=True)
data['kitchen_area'].replace(0, np.nan, inplace=True)
len(data[~data['studio'] &
data['living_area'].isna() &
data['kitchen_area'].isna()])
38
Заполним минимальным значением жилой площади, рассчитанным по известным значениям жилой площади объектов, расположенных во всех населённых пунктах, но в зданиях той же этажности и с тем же количеством жилых комнат.
То же самое выполняем и для значений площади кухни.
for floors in list(data.loc[~data['studio'] &
data['living_area'].isna(),
'floors_total'].sort_values().unique()):
for rooms in list(data.loc[~data['studio'] &
data['living_area'].isna() &
(data['floors_total'] == floors),
'rooms'].sort_values().unique()):
min_value = data.loc[~data['studio'] &
data['living_area'].notna() &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'living_area'].min()
data.loc[~data['studio'] &
data['living_area'].isna() &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'living_area'] = min_value
for floors in list(data.loc[~data['studio'] &
data['kitchen_area'].isna(),
'floors_total'].sort_values().unique()):
for rooms in list(data.loc[~data['studio'] &
data['kitchen_area'].isna() &
(data['floors_total'] == floors),
'rooms'].sort_values().unique()):
min_value = data.loc[~data['studio'] &
data['kitchen_area'].notna() &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'kitchen_area'].min()
data.loc[~data['studio'] &
data['kitchen_area'].isna() &
(data['floors_total'] == floors) &
(data['rooms'] == rooms), 'kitchen_area'] = min_value
Количество записей, для которых не выполняется критерий, что площадь вспомогательных помещений (кроме кухни) должна составлять не менее 2 м².
len(data[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2)])
3
Заменим в таких записях полученное значение жилой площади и значение площади кухни значением NaN.
data.loc[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2),
'living_area'] = 0
data.loc[data['living_area'] == 0, 'kitchen_area'] = 0
data['living_area'].replace(0, np.nan, inplace=True)
data['kitchen_area'].replace(0, np.nan, inplace=True)
len(data[~data['studio'] &
data['living_area'].isna() &
data['kitchen_area'].isna()])
6
Заполним средним арифметическим значением жилой площади, рассчитанным по известным значениям жилой площади объектов, расположенных во всех населённых пунктах, в зданиях любой этажности, но с тем же количеством жилых комнат.
То же самое выполняем и для значений площади кухни.
for rooms in list(data.loc[~data['studio'] &
data['living_area'].isna(),
'rooms'].sort_values().unique()):
mean_value = data.loc[~data['studio'] &
data['living_area'].notna() &
(data['rooms'] == rooms), 'living_area'].mean()
data.loc[~data['studio'] &
data['living_area'].isna() &
(data['rooms'] == rooms), 'living_area'] = mean_value
for rooms in list(data.loc[~data['studio'] &
data['kitchen_area'].isna(),
'rooms'].sort_values().unique()):
mean_value = data.loc[~data['studio'] &
data['kitchen_area'].notna() &
(data['rooms'] == rooms), 'kitchen_area'].mean()
data.loc[~data['studio'] &
data['kitchen_area'].isna() &
(data['rooms'] == rooms), 'kitchen_area'] = mean_value
Количество записей, для которых не удалось рассчитать среднее значение жилой площади.
len(data[~data['studio'] &
data['living_area'].isna() &
data['kitchen_area'].isna()])
0
Количество записей, для которых не выполняется критерий, что площадь вспомогательных помещений (кроме кухни) должна составлять не менее 2 м².
len(data[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2)])
3
Заменим в таких записях полученное значение жилой площади и значение площади кухни значением NaN.
data.loc[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2),
'living_area'] = 0
data.loc[data['living_area'] == 0, 'kitchen_area'] = 0
data['living_area'].replace(0, np.nan, inplace=True)
data['kitchen_area'].replace(0, np.nan, inplace=True)
len(data[~data['studio'] &
data['living_area'].isna() &
data['kitchen_area'].isna()])
3
Заполним минимальным значением жилой площади, рассчитанным по известным значениям жилой площади объектов, расположенных во всех населённых пунктах, в зданиях любой этажности, но с тем же количеством жилых комнат.
То же самое выполняем и для значений площади кухни.
for rooms in list(data.loc[~data['studio'] &
data['living_area'].isna(),
'rooms'].sort_values().unique()):
min_value = data.loc[~data['studio'] &
data['living_area'].notna() &
(data['rooms'] == rooms), 'living_area'].min()
data.loc[~data['studio'] &
data['living_area'].isna() &
(data['rooms'] == rooms), 'living_area'] = min_value
for rooms in list(data.loc[~data['studio'] &
data['kitchen_area'].isna(),
'rooms'].sort_values().unique()):
min_value = data.loc[~data['studio'] &
data['kitchen_area'].notna() &
(data['rooms'] == rooms), 'kitchen_area'].min()
data.loc[~data['studio'] &
data['kitchen_area'].isna() &
(data['rooms'] == rooms), 'kitchen_area'] = min_value
Количество записей, для которых не выполняется критерий, что площадь вспомогательных помещений (кроме кухни) должна составлять не менее 2 м².
len(data[~data['studio'] &
(data['total_area'] < data['living_area'] + data['kitchen_area'] + 2)])
0
Поскольку значения жилой площади и площади кухни определены с точностью до 0,01 м², округлим рассчитанные значения.
data['living_area'] = data['living_area'].round(2)
data['kitchen_area'] = data['kitchen_area'].round(2)
data['living_area'].value_counts().sort_index().head(12).index.tolist()
[6.0, 6.5, 8.0, 8.3, 8.4, 8.5, 8.9, 9.0, 9.1, 9.8, 10.0, 10.08]
data['kitchen_area'].value_counts().sort_index().head(12).index.tolist()
[2.0, 2.3, 2.32, 2.4, 2.55, 2.7, 2.82, 2.85, 2.89, 2.92, 3.0, 3.08]
show_na()
| Всего пропусков | % | |
|---|---|---|
| ponds_nearest | 5421 | 23.1 |
| ponds_around_3000 | 5421 | 23.1 |
| parks_nearest | 5421 | 23.1 |
| parks_around_3000 | 5421 | 23.1 |
| city_centers_nearest | 5421 | 23.1 |
| airports_nearest | 5421 | 23.1 |
| days_exposition | 3153 | 13.4 |
| total_images | 0 | 0.0 |
| kitchen_area | 0 | 0.0 |
| locality_name | 0 | 0.0 |
| balcony | 0 | 0.0 |
| open_plan | 0 | 0.0 |
| last_price | 0 | 0.0 |
| studio | 0 | 0.0 |
| is_apartment | 0 | 0.0 |
| floor | 0 | 0.0 |
| living_area | 0 | 0.0 |
| floors_total | 0 | 0.0 |
| ceiling_height | 0 | 0.0 |
| rooms | 0 | 0.0 |
| first_day_exposition | 0 | 0.0 |
| total_area | 0 | 0.0 |
| locality_type | 0 | 0.0 |
Все пропущенные картографические данные находятся в одних и тех записях. Поскольку для этих записей невозможно восстановить значения картографических признаков, а таких записей значительное количество (23 %), необходимо их заполнить фиктивными значениями — метками. Значения расстояний до центра Санкт-Петербурга, центра аэропорта, ближайших парка и водоёма заполним значением 0 м, которое не противоречит физической природе величины, но в то же время не входит в интервал допустимых значений (не нарушает установленные критерии). Значения количества парков и водоёмов в радиусе 3 км заполним значением (−1).
data.loc[data['city_centers_nearest'].isna(), 'city_centers_nearest'] = 0
data.loc[data['airports_nearest'].isna(), 'airports_nearest'] = 0
data.loc[data['parks_nearest'].isna(), 'parks_nearest'] = 0
data.loc[data['ponds_nearest'].isna(), 'ponds_nearest'] = 0
data.loc[data['parks_around_3000'].isna(), 'parks_around_3000'] = -1
data.loc[data['ponds_around_3000'].isna(), 'ponds_around_3000'] = -1
show_na()
| Всего пропусков | % | |
|---|---|---|
| days_exposition | 3153 | 13.4 |
| total_images | 0 | 0.0 |
| kitchen_area | 0 | 0.0 |
| ponds_nearest | 0 | 0.0 |
| ponds_around_3000 | 0 | 0.0 |
| parks_nearest | 0 | 0.0 |
| parks_around_3000 | 0 | 0.0 |
| city_centers_nearest | 0 | 0.0 |
| airports_nearest | 0 | 0.0 |
| locality_name | 0 | 0.0 |
| balcony | 0 | 0.0 |
| open_plan | 0 | 0.0 |
| last_price | 0 | 0.0 |
| studio | 0 | 0.0 |
| is_apartment | 0 | 0.0 |
| floor | 0 | 0.0 |
| living_area | 0 | 0.0 |
| floors_total | 0 | 0.0 |
| ceiling_height | 0 | 0.0 |
| rooms | 0 | 0.0 |
| first_day_exposition | 0 | 0.0 |
| total_area | 0 | 0.0 |
| locality_type | 0 | 0.0 |
Пропущенные значения признака days_exposition есть преимущественно в записях, опубликованных за последнее время.
sns.heatmap(data.sort_values(by='first_day_exposition').isna(),
cmap=sns.color_palette(['#000000', '#ffffff']))
plt.title('Тепловая карта\nраспределения пропущенных значений')
plt.xlabel('Название признака')
plt.ylabel('Номер записи')
plt.show()
Преобразуем формат object признака first_day_exposition к формату даты и времени.
data['first_day_exposition'] = pd.to_datetime(data['first_day_exposition'],
format='%Y-%m-%dT%H:%M:%S')
data['first_day_exposition'].dtype
dtype('<M8[ns]')
Будем считать, что к моменту выгрузки (к последней дате в наборе данных) все объявления, не имеющие значение в признаке days_exposition, всё ещё оставались опубликованными. Вычислим, какое количество дней прошло с момента публикации до момента получения набора данных и добавим к этому значению 1 день, поскольку на момент получения набора данных объявление ещё не было снято с публикации, а это уже как минимум один день публикации (поскольку время публикации (часы, минуты, секунды) приложением не фиксируется).
Значит, к моменту получения набора данных объявление не было снято в течение стольких дней, сколько прошло с момента публикации до момента получения набора данных.
Для того чтобы дополнительно выделить эти записи, добавим к значению количества дней публикации знак "минус".
data.loc[data['days_exposition'].isna(), 'days_exposition'] = \
(pd.to_timedelta(data['first_day_exposition'].max() -
data.loc[data['days_exposition'].isna(),
'first_day_exposition']).dt.days + 1) * (-1)
data['days_exposition'].sort_values().head(20).unique()
array([-1619., -1608., -1607., -1606., -1605., -1604., -1589., -1582.,
-1570.])
data['days_exposition'].sort_values().tail(20).unique()
array([1396., 1406., 1413., 1417., 1430., 1434., 1441., 1452., 1458.,
1477., 1484., 1485., 1489., 1497., 1512., 1513., 1553., 1572.,
1580.])
show_na()
| Всего пропусков | % | |
|---|---|---|
| total_images | 0 | 0.0 |
| kitchen_area | 0 | 0.0 |
| days_exposition | 0 | 0.0 |
| ponds_nearest | 0 | 0.0 |
| ponds_around_3000 | 0 | 0.0 |
| parks_nearest | 0 | 0.0 |
| parks_around_3000 | 0 | 0.0 |
| city_centers_nearest | 0 | 0.0 |
| airports_nearest | 0 | 0.0 |
| locality_name | 0 | 0.0 |
| balcony | 0 | 0.0 |
| open_plan | 0 | 0.0 |
| last_price | 0 | 0.0 |
| studio | 0 | 0.0 |
| is_apartment | 0 | 0.0 |
| floor | 0 | 0.0 |
| living_area | 0 | 0.0 |
| floors_total | 0 | 0.0 |
| ceiling_height | 0 | 0.0 |
| rooms | 0 | 0.0 |
| first_day_exposition | 0 | 0.0 |
| total_area | 0 | 0.0 |
| locality_type | 0 | 0.0 |
data.dtypes
total_images int64 last_price float64 total_area float64 first_day_exposition datetime64[ns] rooms int64 ceiling_height float64 floors_total float64 living_area float64 floor int64 is_apartment bool studio bool open_plan bool kitchen_area float64 balcony float64 locality_name object airports_nearest float64 city_centers_nearest float64 parks_around_3000 float64 parks_nearest float64 ponds_around_3000 float64 ponds_nearest float64 days_exposition float64 locality_type object dtype: object
Значения признаков last_price, floors_total, balcony, parks_around_3000, ponds_around_3000, days_exposition являются целочисленными, а значения признаков city_centers_nearest, airports_nearest, parks_nearest, ponds_nearest определены с точностью до 1 м, поэтому их тип необходимо изменить на int64.
columns = ['last_price', 'floors_total', 'balcony', 'city_centers_nearest',
'airports_nearest', 'parks_nearest', 'ponds_nearest',
'parks_around_3000', 'ponds_around_3000', 'days_exposition']
data[columns] = data[columns].astype('int64')
data.dtypes
total_images int64 last_price int64 total_area float64 first_day_exposition datetime64[ns] rooms int64 ceiling_height float64 floors_total int64 living_area float64 floor int64 is_apartment bool studio bool open_plan bool kitchen_area float64 balcony int64 locality_name object airports_nearest int64 city_centers_nearest int64 parks_around_3000 int64 parks_nearest int64 ponds_around_3000 int64 ponds_nearest int64 days_exposition int64 locality_type object dtype: object
Полные дубликаты в наборе данных отсутствуют.
data.duplicated().sum()
0
Кандидатов в дубли в наборе данных — 21. Кандидаты в дубли выявлены по данным об объекте недвижимости (общей площади, количестве комнат, этаже), по данным о здании (этажность, местоположение) и по дате публикации. Все эти данные были изначально в наборе данных заполненными (практически полностью). Кроме того, день публикации является обязательным критерием сравнения, поскольку объявления о продаже одного и того же объекта недвижимости может публиковаться несколько раз, что может свидетельствовать о перепродаже этого объекта.
columns = ['first_day_exposition', 'total_area', 'rooms',
'floor', 'locality_name', 'floors_total']
data[columns][data.duplicated(columns, keep=False)] \
.sort_values(by=['first_day_exposition', 'total_area']).head(10)
| first_day_exposition | total_area | rooms | floor | locality_name | floors_total | |
|---|---|---|---|---|---|---|
| 5783 | 2015-02-09 | 35.46 | 1 | 20 | Санкт-Петербург | 21 |
| 10852 | 2015-02-09 | 35.46 | 1 | 20 | Санкт-Петербург | 21 |
| 5155 | 2017-04-14 | 84.10 | 2 | 4 | Санкт-Петербург | 5 |
| 17989 | 2017-04-14 | 84.10 | 2 | 4 | Санкт-Петербург | 5 |
| 6827 | 2017-08-15 | 60.00 | 3 | 8 | Санкт-Петербург | 9 |
| 18534 | 2017-08-15 | 60.00 | 3 | 8 | Санкт-Петербург | 9 |
| 5241 | 2017-09-13 | 30.00 | 1 | 5 | Санкт-Петербург | 9 |
| 12650 | 2017-09-13 | 30.00 | 1 | 5 | Санкт-Петербург | 9 |
| 1666 | 2017-10-13 | 34.00 | 1 | 7 | Санкт-Петербург | 9 |
| 16291 | 2017-10-13 | 34.00 | 1 | 7 | Санкт-Петербург | 9 |
data[columns].duplicated().sum()
21
len(data)
23460
Удаляем кандидаты в дубликаты.
data.drop_duplicates(subset=columns, inplace=True)
data[columns].duplicated().sum()
0
len(data)
23439
Последние приготовления.
Отсортируем записи по значению дня публикации в хронологическом порядке и проиндексируем записи непрерывным рядом значений.
data = data.sort_values(by='first_day_exposition').reset_index(drop=True)
data.head()
| total_images | last_price | total_area | first_day_exposition | rooms | ceiling_height | floors_total | living_area | floor | is_apartment | studio | open_plan | kitchen_area | balcony | locality_name | airports_nearest | city_centers_nearest | parks_around_3000 | parks_nearest | ponds_around_3000 | ponds_nearest | days_exposition | locality_type | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 7 | 20100000 | 117.60 | 2014-11-27 | 3 | 3.0 | 8 | 62.50 | 7 | False | False | False | 21.50 | 0 | Санкт-Петербург | 39393 | 11096 | 1 | 537 | 0 | 0 | -1619 | город |
| 1 | 1 | 12036000 | 100.00 | 2014-11-27 | 3 | 2.7 | 16 | 52.00 | 3 | False | False | False | 11.00 | 1 | Санкт-Петербург | 37407 | 8434 | 1 | 456 | 2 | 454 | 606 | город |
| 2 | 2 | 14500000 | 97.40 | 2014-11-27 | 2 | 3.0 | 8 | 36.30 | 2 | False | False | False | 31.70 | 0 | Санкт-Петербург | 39393 | 11096 | 1 | 537 | 0 | 0 | 1078 | город |
| 3 | 2 | 16137000 | 154.76 | 2014-11-27 | 4 | 2.7 | 20 | 67.81 | 20 | False | False | False | 32.55 | 0 | Санкт-Петербург | 18490 | 17492 | 0 | 0 | 2 | 113 | 573 | город |
| 4 | 8 | 8200000 | 52.50 | 2014-11-27 | 1 | 3.0 | 8 | 21.50 | 2 | False | False | False | 15.10 | 0 | Санкт-Петербург | 39393 | 11096 | 1 | 537 | 0 | 0 | -1619 | город |
data.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 23439 entries, 0 to 23438 Data columns (total 23 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 total_images 23439 non-null int64 1 last_price 23439 non-null int64 2 total_area 23439 non-null float64 3 first_day_exposition 23439 non-null datetime64[ns] 4 rooms 23439 non-null int64 5 ceiling_height 23439 non-null float64 6 floors_total 23439 non-null int64 7 living_area 23439 non-null float64 8 floor 23439 non-null int64 9 is_apartment 23439 non-null bool 10 studio 23439 non-null bool 11 open_plan 23439 non-null bool 12 kitchen_area 23439 non-null float64 13 balcony 23439 non-null int64 14 locality_name 23439 non-null object 15 airports_nearest 23439 non-null int64 16 city_centers_nearest 23439 non-null int64 17 parks_around_3000 23439 non-null int64 18 parks_nearest 23439 non-null int64 19 ponds_around_3000 23439 non-null int64 20 ponds_nearest 23439 non-null int64 21 days_exposition 23439 non-null int64 22 locality_type 23439 non-null object dtypes: bool(3), datetime64[ns](1), float64(4), int64(13), object(2) memory usage: 3.6+ MB
Создание признака "Последний день публикации объявления".
data['last_day_exposition'] = (pd.to_datetime(data['first_day_exposition']) + \
pd.to_timedelta(abs(data['days_exposition']),
unit='D')).dt.date
data['last_day_exposition'] = pd.to_datetime(data['last_day_exposition'])
data[['first_day_exposition', 'last_day_exposition']].head()
| first_day_exposition | last_day_exposition | |
|---|---|---|
| 0 | 2014-11-27 | 2019-05-04 |
| 1 | 2014-11-27 | 2016-07-25 |
| 2 | 2014-11-27 | 2017-11-09 |
| 3 | 2014-11-27 | 2016-06-22 |
| 4 | 2014-11-27 | 2019-05-04 |
data['last_day_exposition'].dtypes
dtype('<M8[ns]')
Перевод значений расстояний в километры.
data['city_centers_km'] = (data['city_centers_nearest'] / 1000).round(1)
data['airports_km'] = (data['airports_nearest'] / 1000).round(1)
data['parks_km'] = (data['parks_nearest'] / 1000).round(1)
data['ponds_km'] = (data['ponds_nearest'] / 1000).round(1)
Создание признака "Цена одного квадратного метра".
data['price_per_square_meter'] = (data['last_price'] / data['total_area']).round(0)
data['price_per_square_meter'] = data['price_per_square_meter'].astype('int')
Создание признаков "День недели", "Месяц", "Год" публикации объявления.
data['year'] = data['first_day_exposition'].dt.year
data['month'] = data['first_day_exposition'].dt.month
data['weekday'] = data['first_day_exposition'].dt.weekday
data.columns
Index(['total_images', 'last_price', 'total_area', 'first_day_exposition',
'rooms', 'ceiling_height', 'floors_total', 'living_area', 'floor',
'is_apartment', 'studio', 'open_plan', 'kitchen_area', 'balcony',
'locality_name', 'airports_nearest', 'city_centers_nearest',
'parks_around_3000', 'parks_nearest', 'ponds_around_3000',
'ponds_nearest', 'days_exposition', 'locality_type',
'last_day_exposition', 'city_centers_km', 'airports_km', 'parks_km',
'ponds_km', 'price_per_square_meter', 'year', 'month', 'weekday'],
dtype='object')
Создание признака "Тип этажа квартиры".
def floor_type_categorize(row):
if row['floor'] == 1:
return 'первый'
elif row['floor'] == row['floors_total']:
return 'последний'
else:
return 'другой'
data['floor_type'] = data.apply(floor_type_categorize, axis = 1)
data['floor_type'].unique()
array(['другой', 'последний', 'первый'], dtype=object)
data[['floor', 'floors_total', 'floor_type']].sample(7)
| floor | floors_total | floor_type | |
|---|---|---|---|
| 18041 | 3 | 6 | другой |
| 8935 | 2 | 9 | другой |
| 11190 | 8 | 10 | другой |
| 14855 | 1 | 4 | первый |
| 10687 | 3 | 6 | другой |
| 1746 | 3 | 5 | другой |
| 5322 | 13 | 16 | другой |
Создание признака "Является Санкт-Петербургом".
Обозначим некоторые населённые пункты, находящиеся в черте города Санкт-Петербурга, как Санкт-Петербург.
spb_locality = [
'Зеленогорск', 'Колпино', 'Красное Село', 'Кронштадт', 'Ломоносов',
'Павловск', 'Петергоф', 'Пушкин', 'Сестрорецк', 'Александровская',
'Белоостров', 'Левашово', 'Лисий Нос', 'Металлострой', 'Молодёжное',
'Парголово', 'Петро-Славянка', 'Понтонный', 'Репино', 'Сапёрный',
'Стрельна', 'Усть-Ижора', 'Шушары', 'Санкт-Петербург'
]
for index in range(len(data)):
if data.loc[index, 'locality_name'] in spb_locality:
data.loc[index, 'is_spb'] = True
else:
data.loc[index, 'is_spb'] = False
Внесём данные о расстоянии до центра Санкт-Петербурга и аэропорта от населённых пунктов, расположенных в черте Санкт-Петербурга. Расстояния рассчитаем как среднее арифметическое значений, которые уже имеются в наборе данных для этих населённых пунктов.
for locality in list(data.loc[data['is_spb'] &
(data['city_centers_km'] == 0),
'locality_name'].unique()):
data.loc[data['is_spb'] &
(data['city_centers_km'] == 0) &
(data['locality_name'] == locality),
'city_centers_km'] = data.loc[data['locality_name'] == locality,
'city_centers_km'].mean().round(1)
data.loc[data['is_spb'] &
(data['city_centers_km'] == 0) &
(data['locality_name'] == locality),
'airports_km'] = data.loc[data['locality_name'] == locality,
'airports_km'].mean().round(1)
data['is_spb'].unique()
array([True, False], dtype=object)
data.columns
Index(['total_images', 'last_price', 'total_area', 'first_day_exposition',
'rooms', 'ceiling_height', 'floors_total', 'living_area', 'floor',
'is_apartment', 'studio', 'open_plan', 'kitchen_area', 'balcony',
'locality_name', 'airports_nearest', 'city_centers_nearest',
'parks_around_3000', 'parks_nearest', 'ponds_around_3000',
'ponds_nearest', 'days_exposition', 'locality_type',
'last_day_exposition', 'city_centers_km', 'airports_km', 'parks_km',
'ponds_km', 'price_per_square_meter', 'year', 'month', 'weekday',
'floor_type', 'is_spb'],
dtype='object')
Промежуточный вывод
Предварительно зададим функцию, рассчитывающую описательные статистики.
def descriptive_statistics(values, label):
'''
Описательная статистика переменной, измеряемой в количественной шкале.
Принимает значения признака и название признака.
Возвращает DataFrame с набором статистик.
'''
df = pd.DataFrame([
values.count(),
len(values.unique()),
values.min(),
values.median() - 1.5 * (values.quantile(q=.75) -
values.quantile(q=.25)),
values.quantile(q=.25).round(2),
(values.mode()).to_list(),
values.median().round(2),
values.mean().round(2),
values.quantile(q=.75).round(2),
values.median() + 1.5 * (values.quantile(q=.75) -
values.quantile(q=.25)),
values.max(),
values.max() - values.min(),
values.quantile(q=.75) - values.quantile(q=.25)
],
index=['кол-во значений', 'кол-во уникальных', 'мин.',
'-1.5IQR', '25 %', 'мода', 'медиана',
'среднее ариф.', '75 %', '+1.5IQR', 'макс.',
'размах', 'межквартильный размах'],
columns=[label])
return df
stat = pd.DataFrame(
pd.to_datetime(data['first_day_exposition']).dt.date.describe()
).rename(columns={'first_day_exposition': 'День публикации'},
index={'count': 'кол-во значений',
'unique': 'кол-во уникальных',
'top': 'мода',
'freq': 'частота моды'}
).T
stat.loc['День публикации', 'мода'] = \
stat.loc['День публикации', 'мода'].strftime('%d.%m.%Y')
stat['мин'] = data['first_day_exposition'].min().strftime('%d.%m.%Y')
stat['медиана'] = data['first_day_exposition'].quantile(q=.5).strftime('%d.%m.%Y')
stat['макс'] = data['first_day_exposition'].max().strftime('%d.%m.%Y')
stat['размах'] = (data['first_day_exposition'].max() -
data['first_day_exposition'].min()).days + 1
stat['межквартильный размах'] = (data['first_day_exposition'].quantile(q=.75) -
data['first_day_exposition'].quantile(q=.25)).days
stat.T
| День публикации | |
|---|---|
| кол-во значений | 23439 |
| кол-во уникальных | 1490 |
| мода | 01.02.2018 |
| частота моды | 359 |
| мин | 27.11.2014 |
| медиана | 11.12.2017 |
| макс | 03.05.2019 |
| размах | 1619 |
| межквартильный размах | 470 |
data['first_day_exposition'].value_counts().plot.box(
title='Диаграма размаха распределения количества объявлений в день',
xlabel='Количество объявлений в день',
vert=False,
figsize=(10, 2))
plt.tick_params(left=False, labelleft=False)
plt.show()
data['first_day_exposition'].value_counts().value_counts().sort_index().plot.bar(
title='Диаграмма распределения количества дней ' +
'по количеству публикуемых в день объявлений',
xlabel='Количество объявлений в день',
ylabel='Количество дней',
figsize=(20, 5))
plt.show()
Медианное значение количества публикуемых в день объявлений
data['first_day_exposition'].value_counts().median()
10.0
data.loc[data['is_spb'], 'first_day_exposition'].value_counts().plot.box(
title='Диаграма размаха распределения количества' +
'\nобъявлений в день о квартирах, расположенных в Санкт-Петербурге',
xlabel='Количество объявлений в день',
vert=False,
figsize=(10, 2))
plt.tick_params(left=False, labelleft=False)
plt.show()
plt.title('Диаграмма распределения количества дней' +
'\nпо количеству публикуемых в день объявлений')
data.loc[data['is_spb'], 'first_day_exposition'].value_counts().plot.hist(
bins=[n + 1 for n in range(70)],
figsize=(10, 3))
plt.xlabel('Количество объявлений в день')
plt.ylabel('Количество дней')
plt.show()
data['year'].value_counts().describe().round(2)
count 6.00 mean 3906.50 std 3521.10 min 134.00 25% 1577.75 50% 2803.50 75% 6795.25 max 8403.00 Name: count, dtype: float64
data['year'].value_counts().sort_index().plot.bar(
rot=0,
title='Диаграмма распределения\nколичества объявлений по годам публикации',
xlabel='Год публикации',
ylabel='Количество объявлений',
figsize=(6, 3))
plt.show()
Таблица относительных частот.
pd.DataFrame((data['year'].value_counts() /
data.shape[0] * 100).round(0).astype('int')) \
.sort_index().reset_index() \
.rename(columns={
'year': 'Год',
'count': 'Относительная частота, %'}
).set_index('Год').T
| Год | 2014 | 2015 | 2016 | 2017 | 2018 | 2019 |
|---|---|---|---|---|---|---|
| Относительная частота, % | 1 | 5 | 12 | 35 | 36 | 12 |
pd.DataFrame(data.loc[(data['year'] > 2014) &
(data['year'] < 2019), 'year'].value_counts().sort_index()
).rename(columns={'count': 'Кол-во объявлений'}).plot.pie(
figsize=(4, 4),
title='Круговая диаграмма\nраспределения количества объявлений' +
'\nпо годам за 2015—2018 гг.',
subplots=True,
ylabel='',
legend=False,
table=True)
plt.show()
Таблица относительных частот.
pd.DataFrame((data.loc[(data['year'] > 2014) &
(data['year'] < 2019), 'year'].value_counts() /
data[(data['year'] > 2014) &
(data['year'] < 2019)].shape[0] * 100).round(0).astype('int')) \
.sort_index().reset_index() \
.rename(columns={
'year': 'Год',
'count': 'Относительная частота, %'}
).set_index('Год').T
| Год | 2015 | 2016 | 2017 | 2018 |
|---|---|---|---|---|
| Относительная частота, % | 6 | 13 | 40 | 41 |
Описательная статистика значений частот.
data['month'].value_counts().describe()
count 12.000000 mean 1953.250000 std 438.902376 min 1259.000000 25% 1655.000000 50% 1854.500000 75% 2348.750000 max 2608.000000 Name: count, dtype: float64
plt.title('Диаграмма распределения\nколичества объявлений по месяцам')
data['month'].value_counts().sort_index().plot.bar(
rot=0,
figsize=(6, 3))
plt.xlabel('Месяц')
plt.ylabel('Количество объявлений')
plt.xticks(np.arange(12), ['янв.', 'фев.', 'мар.', 'апр.', 'май', 'июн.',
'июл.', 'авг.', 'сент.', 'окт.', 'нояб.', 'дек.'])
plt.show()
Таблица относительных частот.
pd.DataFrame((data['month'].value_counts() /
data.shape[0] * 100).round(0).astype('int')) \
.sort_index().reset_index() \
.rename(columns={
'month': 'Месяц',
'count': 'Относительная частота, %'}
).set_index('Месяц').T
| Месяц | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Относительная частота, % | 6 | 11 | 11 | 10 | 5 | 7 | 7 | 7 | 8 | 9 | 10 | 7 |
Описательная статистика значений частот, рассчитанных для набора данных за период 2015—2018 гг.
data.loc[(data['year'] > 2014) &
(data['year'] < 2019), 'month'].value_counts().describe().round(2)
count 12.00 mean 1705.00 std 372.81 min 1069.00 25% 1480.25 50% 1709.00 75% 1986.50 max 2328.00 Name: count, dtype: float64
plt.title('Диаграмма распределения\nколичества объявлений по месяцам' +
'\nза период 2015—2018 гг.')
data.loc[(data['year'] > 2014) &
(data['year'] < 2019), 'month'].value_counts().sort_index().plot.bar(
rot=0, figsize=(6, 3))
plt.xlabel('Месяц')
plt.ylabel('Количество объявлений')
plt.xticks(np.arange(12), ['янв.', 'фев.', 'мар.', 'апр.', 'май', 'июн.',
'июл.', 'авг.', 'сент.', 'окт.', 'нояб.', 'дек.'])
plt.show()
plt.title('Диаграмма распределения\nколичества объявлений по каждому месяцу')
data['first_day_exposition'].groupby([data['first_day_exposition'].dt.year,
data['first_day_exposition'].dt.month]
).count().plot.bar(figsize=(10, 3))
plt.xlabel('Год и месяц публикации')
plt.ylabel('Количество объявлений')
plt.show()
Топ-10 дней с наибольшим количеством объявлений в день.
data['first_day_exposition'].value_counts().head(10).sort_index()
first_day_exposition 2017-09-27 109 2017-09-28 74 2017-10-13 121 2017-11-10 239 2018-01-12 70 2018-02-01 359 2018-02-08 71 2018-03-06 70 2018-03-26 97 2018-07-10 92 Name: count, dtype: int64
plt.title('Диаграмма распределения\nколичества объявлений по каждому дню ' +
'за период 01.01—28.02.2018 гг.')
data.loc[(data['year'] == 2018) & (data['month'] <= 2),
'first_day_exposition'].groupby([data['first_day_exposition'].dt.month,
data['first_day_exposition'].dt.day]
).count().plot.bar(figsize=(10, 3))
plt.xlabel('Месяц и число публикации')
plt.ylabel('Количество объявлений')
plt.show()
plt.title('Диаграмма распределения\nколичества объявлений по каждому дню ' +
'за период 01.09—30.11.2017 гг.')
data.loc[(data['year'] == 2017) & (data['month'] >= 9) & (data['month'] <= 11),
'first_day_exposition'].groupby([data['first_day_exposition'].dt.month,
data['first_day_exposition'].dt.day]
).count().plot.bar(figsize=(15, 3))
plt.xlabel('Месяц и число публикации')
plt.ylabel('Количество объявлений')
plt.show()
plt.title('Диаграмма распределения\nколичества объявлений по числам октября ' +
'за 2015—2016 гг.')
data.loc[(data['year'] < 2017) & (data['month'] == 10),
'first_day_exposition'].groupby([data['first_day_exposition'].dt.year,
data['first_day_exposition'].dt.day]
).count().plot.bar(figsize=(10, 3))
plt.xlabel('Год и число публикации')
plt.ylabel('Количество объявлений')
plt.show()
data['day'] = pd.DatetimeIndex(data['first_day_exposition']).day
plt.title('Диаграмма распределения\nколичества объявлений, ' +
'опубликованных 31 декабря или 1 января')
data.loc[((data['day'] == 31) & (data['month'] == 12)) |
((data['day'] == 1) & (data['month'] == 1)),
'first_day_exposition'].groupby([data['first_day_exposition'].dt.year,
data['first_day_exposition'].dt.day]
).count().plot.bar(rot=0, figsize=(10, 3))
plt.xlabel('Год и число публикации')
plt.ylabel('Количество объявлений')
plt.show()
plt.title('Диаграмма распределения\nколичества объявлений по дням недели')
data['weekday'].value_counts().sort_index().plot.bar(rot=0, figsize=(5, 3))
plt.xlabel('День недели')
plt.ylabel('Количество объявлений')
plt.xticks(np.arange(7), ['пн', 'вт', 'ср', 'чт', 'пт', 'сб', 'вс'])
plt.show()
Таблица относительных частот.
pd.DataFrame((data['weekday'].value_counts() /
data.shape[0] * 100).sort_index().round(0).astype('int')) \
.sort_index().reset_index() \
.rename(columns={
'weekday': 'День недели',
'count': 'Относительная частота, %'}
).set_index('День недели').rename(
index={0: 'пн', 1: 'вт', 2: 'ср', 3: 'чт', 4: 'пт', 5: 'сб', 6: 'вс'}
).T
| День недели | пн | вт | ср | чт | пт | сб | вс |
|---|---|---|---|---|---|---|---|
| Относительная частота, % | 15 | 18 | 17 | 18 | 17 | 8 | 7 |
plt.title('Диаграмма распределения' +
'\nколичества объявлений по месяцам и дням недели в течение 2018 года')
data.loc[data['year'] == 2018,
'first_day_exposition'].groupby([data['first_day_exposition'].dt.month,
data['first_day_exposition'].dt.weekday]
).count().plot.bar(figsize=(15, 3))
plt.xlabel('Месяц и день недели')
plt.ylabel('Количество объявлений')
plt.show()
descriptive_statistics(data.loc[data['days_exposition'] > 0, 'days_exposition'],
'Количество дней публикации')
| Количество дней публикации | |
|---|---|
| кол-во значений | 20289 |
| кол-во уникальных | 1141 |
| мин. | 1 |
| -1.5IQR | -184.5 |
| 25 % | 45.0 |
| мода | [45] |
| медиана | 96.0 |
| среднее ариф. | 181.42 |
| 75 % | 232.0 |
| +1.5IQR | 376.5 |
| макс. | 1580 |
| размах | 1579 |
| межквартильный размах | 187.0 |
data.loc[data['days_exposition'] > 0, 'days_exposition'].plot.box(
title='Диаграмма размаха' +
'\nраспределения количества объявлений по количеству дней публикации' +
'\n(для объявлений, снятых с публикации)',
xlabel='Количество дней публикации',
vert=False,
figsize=(10, 2))
plt.tick_params(left=False, labelleft=False)
plt.show()
plt.title('Диаграмма распределения' +
'\nколичества объявлений по количеству дней публикации' +
'\n(для объявлений, снятых с публикации)')
data.loc[data['days_exposition'] > 0, 'days_exposition'].plot.hist(
bins=[n + 1 for n in range(1580)],
figsize=(10, 3))
plt.xlabel('Количество дней публикации')
plt.ylabel('Количество объявлений')
plt.ylim(0, 599)
plt.show()
plt.title('Диаграмма распределения' +
'\nколичества объявлений по количеству дней публикации' +
'\n(для объявлений, снятых с публикации)')
data.loc[data['days_exposition'] > 0, 'days_exposition'].plot.hist(
bins=[n + 1 for n in range(100)],
figsize=(10, 3))
plt.xlabel('Количество дней публикации')
plt.ylabel('Количество объявлений')
plt.show()
Топ-10 количества дней публикации.
data.loc[data['days_exposition'] > 0, 'days_exposition'].value_counts().head(10)
days_exposition 45 873 60 532 7 224 30 208 90 204 4 174 3 156 5 150 14 147 9 140 Name: count, dtype: int64
days_exposed = data.loc[data['days_exposition'] > 0, 'days_exposition']
first_week = (days_exposed <= 7).sum()
second_week = ((days_exposed > 7) & (days_exposed <= 14)).sum()
first_month = ((days_exposed > 14) & (days_exposed <= 30)).sum()
month_and_half = ((days_exposed > 30) & (days_exposed <= 45)).sum()
second_month = ((days_exposed > 45) & (days_exposed <= 60)).sum()
third_month = ((days_exposed > 60) & (days_exposed <= 90)).sum()
half_year = ((days_exposed > 90) & (days_exposed <= 180)).sum()
first_year = ((days_exposed > 180) & (days_exposed <= 365)).sum()
more = (days_exposed > 365).sum()
days_exposed_category = pd.Series({'7 дн.': first_week,
'14 дн.': second_week,
'30 дн.': first_month,
'45 дн.': month_and_half,
'60 дн.': second_month,
'90 дн.': third_month,
'180 дн.': half_year,
'365 дн.': first_year,
'более года': more})
plt.title('Круговая диаграмма\nраспределения количества объявлений' +
'\nпо количеству дней публикации\n(для объявлений, снятых с публикации)')
days_exposed_category.plot.pie(figsize=(4, 4))
plt.show()
Таблица относительных и куммулятивных частот.
days_exposed_category_percent = pd.DataFrame(
days_exposed_category /
len(days_exposed) * 100).round(0).astype('int').rename(
columns={0: 'Относительная частота, %'}
)
days_exposed_category_percent['Накопленная частота, %'] = \
days_exposed_category_percent.cumsum(axis=0)
days_exposed_category_percent.T
| 7 дн. | 14 дн. | 30 дн. | 45 дн. | 60 дн. | 90 дн. | 180 дн. | 365 дн. | более года | |
|---|---|---|---|---|---|---|---|---|---|
| Относительная частота, % | 4 | 5 | 10 | 11 | 8 | 11 | 20 | 17 | 15 |
| Накопленная частота, % | 4 | 9 | 19 | 30 | 38 | 49 | 69 | 86 | 101 |
Описательная статистика набора значений, относящихся к объявлениям, ещё не снятым с публикации.
abs(data.loc[data['days_exposition'] < 0,
'days_exposition']).describe().round(0).astype('int')
count 3150 mean 219 std 306 min 1 25% 32 50% 82 75% 277 max 1619 Name: days_exposition, dtype: int32
abs(data.loc[data['days_exposition'] < 0, 'days_exposition']).plot.box(
title='Диаграмма размаха' +
'\nраспределения количества объявлений по количеству дней публикации' +
'\n(для объявлений, не снятых с публикации)',
vert=False,
xlabel='Количество дней публикации',
figsize=(10, 2))
plt.tick_params(left=False, labelleft=False)
plt.show()
plt.title('Диаграмма распределения' +
'\nколичества объявлений по количеству дней публикации' +
'\n(для объявлений, не снятых с публикации)')
abs(data.loc[data['days_exposition'] < 0, 'days_exposition']).plot.hist(
bins=[n + 1 for n in range(1619)],
figsize=(10, 3))
plt.xlabel('Количество дней публикации')
plt.ylabel('Количество объявлений')
plt.ylim(0, 39)
plt.show()
days_exposed = data.loc[data['days_exposition'] < 0, 'days_exposition']
days_exposed = abs(days_exposed)
first_week = (days_exposed <= 7).sum()
second_week = ((days_exposed > 7) & (days_exposed <= 14)).sum()
first_month = ((days_exposed > 14) & (days_exposed <= 30)).sum()
month_and_half = ((days_exposed > 30) & (days_exposed <= 45)).sum()
second_month = ((days_exposed > 45) & (days_exposed <= 60)).sum()
third_month = ((days_exposed > 60) & (days_exposed <= 90)).sum()
half_year = ((days_exposed > 90) & (days_exposed <= 180)).sum()
first_year = ((days_exposed > 180) & (days_exposed <= 365)).sum()
more = (days_exposed > 365).sum()
days_exposed_category = pd.Series({'7 дн.': first_week,
'14 дн.': second_week,
'30 дн.': first_month,
'45 дн.': month_and_half,
'60 дн.': second_month,
'90 дн.': third_month,
'180 дн.': half_year,
'365 дн.': first_year,
'более года': more})
plt.title('Круговая диаграмма\nраспределения количества объявлений' +
'\nпо количеству дней публикации' +
'\n(для объявлений, не снятых с публикации)')
days_exposed_category.plot.pie(figsize=(3, 3))
plt.show()
Таблица относительных и куммулятивных частот.
days_exposed_category_percent = pd.DataFrame(
days_exposed_category /
len(days_exposed)*100).round(0).astype('int').rename(
columns={0: 'Относительная частота, %'}
)
days_exposed_category_percent['Накопленная частота, %'] = \
days_exposed_category_percent.cumsum(axis=0)
days_exposed_category_percent.T
| 7 дн. | 14 дн. | 30 дн. | 45 дн. | 60 дн. | 90 дн. | 180 дн. | 365 дн. | более года | |
|---|---|---|---|---|---|---|---|---|---|
| Относительная частота, % | 5 | 6 | 13 | 9 | 8 | 10 | 12 | 16 | 20 |
| Накопленная частота, % | 5 | 11 | 24 | 33 | 41 | 51 | 63 | 79 | 99 |
stat = pd.DataFrame(pd.to_datetime(
data.loc[data['days_exposition'] > 0,
'last_day_exposition']).dt.date.describe()
).rename(columns={'last_day_exposition': 'Последний день публикации'},
index={'count': 'кол-во значений',
'unique': 'кол-во уникальных',
'top': 'мода',
'freq': 'частота моды'}
).T
stat.loc['Последний день публикации', 'мода'] = \
stat.loc['Последний день публикации', 'мода'].strftime('%d.%m.%Y')
stat['мин'] = data.loc[data['days_exposition'] > 0,
'last_day_exposition'].min().strftime('%d.%m.%Y')
stat['медиана'] = data.loc[data['days_exposition'] > 0,
'last_day_exposition'].quantile(q=.5).strftime('%d.%m.%Y')
stat['макс'] = data.loc[data['days_exposition'] > 0,
'last_day_exposition'].max().strftime('%d.%m.%Y')
stat['размах'] = (data.loc[data['days_exposition'] > 0, 'last_day_exposition'].max() -
data.loc[data['days_exposition'] > 0, 'last_day_exposition'].min()).days + 1
stat['межквартильный размах'] = (data.loc[data['days_exposition'] > 0,
'last_day_exposition'].quantile(q=.75) -
data.loc[data['days_exposition'] > 0,
'last_day_exposition'].quantile(q=.25)).days
stat.T
| Последний день публикации | |
|---|---|
| кол-во значений | 20289 |
| кол-во уникальных | 1038 |
| мода | 23.01.2018 |
| частота моды | 487 |
| мин | 16.06.2016 |
| медиана | 04.04.2018 |
| макс | 02.05.2019 |
| размах | 1051 |
| межквартильный размах | 371 |
data.loc[data['days_exposition'] > 0,
'last_day_exposition'].value_counts().plot.box(
title='Диаграмма размаха\nраспределения количества объявлений,' +
'\nснятых с публикации за один день',
vert=False,
xlabel='Количество объявлений',
figsize=(10, 2))
plt.tick_params(left=False, labelleft=False)
plt.show()
data.loc[data['days_exposition'] > 0,
'last_day_exposition'].value_counts().value_counts().sort_index().plot.bar(
title='Диаграмма распределения количества дней по количеству объявлений, ' +
'снятых с публикации за один день',
xlabel='Количество снятых с публикации объявлений в день',
ylabel='Количество дней',
figsize=(15, 5))
plt.show()
plt.title('Диаграмма распределения\nколичества объявлений' +
'\nпо году и месяцу снятия объявления с публикации')
data.loc[data['days_exposition'] > 0,
'last_day_exposition'].groupby([data['last_day_exposition'].dt.year,
data['last_day_exposition'].dt.month]
).count().plot.bar(figsize=(10, 3))
plt.xlabel('Год и месяц снятия с публикации')
plt.ylabel('Количество объявлений')
plt.show()
Выеделение сведений о годе, месяце и дне недели последнего дня публикации.
data['last_year'] = pd.DatetimeIndex(data['last_day_exposition']).year
data['last_month'] = pd.DatetimeIndex(data['last_day_exposition']).month
data['last_weekday'] = pd.DatetimeIndex(data['last_day_exposition']).weekday
Топ-5 дней снятия объявления с публикации с максимальным количеством снятых объявлений в день.
data.loc[data['days_exposition'] > 0, 'last_day_exposition'].value_counts().head()
last_day_exposition 2018-01-23 487 2018-03-26 106 2018-09-15 100 2018-12-18 94 2019-04-13 83 Name: count, dtype: int64
plt.title('Диаграмма распределения' +
'\nколичества объявлений по числу снятия с публикации ' +
'в период 01.01—28.02.2018 гг.')
data.loc[(data['days_exposition'] > 0) &
(data['last_year'] == 2018) &
(data['last_month'] <= 2),
'last_day_exposition'].groupby([data['last_day_exposition'].dt.month,
data['last_day_exposition'].dt.day]
).count().plot.bar(figsize=(10, 3))
plt.xlabel('Месяц и число снятия с публикации')
plt.ylabel('Количество объявлений')
plt.show()
plt.title('Диаграмма распределения' +
'\nколичества объявлений по году снятия с публикации')
data.loc[data['days_exposition'] > 0,
'last_year'].value_counts().sort_index().plot.bar(rot=0, figsize=(7, 3))
plt.xlabel('Год')
plt.ylabel('Количество объявлений')
plt.show()
plt.title('Диаграмма распределения' +
'\nколичества объявлений по месяцу снятия с публикации')
data.loc[(data['days_exposition'] > 0) &
(data['last_year'] > 2016) &
(data['last_year'] < 2019),
'last_month'].value_counts().sort_index().plot.bar(rot=0, figsize=(7, 3))
plt.xlabel('Месяц')
plt.ylabel('Количество объявлений')
plt.xticks(np.arange(12), ['янв.', 'фев.', 'мар.', 'апр.', 'май', 'июн.',
'июл.', 'авг.', 'сент.', 'окт.', 'нояб.', 'дек.'])
plt.show()
plt.title('Диаграмма распределения\nколичества объявлений' +
'\nпо дням недели снятия объявления с публикации')
data.loc[data['days_exposition'] > 0,
'last_weekday'].value_counts().sort_index().plot.bar(rot=0, figsize=(7, 3))
plt.xlabel('День недели')
plt.ylabel('Количество объявлений')
plt.xticks(np.arange(7), ['пн', 'вт', 'ср', 'чт', 'пт', 'сб', 'вс'])
plt.show()
data['is_spb'].astype('int').value_counts().rename(
index={0: 'Область', 1: 'Город'}).plot.pie(
title='Круговая диаграмма\nраспределения объявлений между' +
'\nСанкт-Петербургом и Ленинградской областью',
label='',
figsize=(4, 4))
plt.show()
pd.DataFrame((data['is_spb'].astype('int').value_counts() /
data.shape[0] * 100).round(0).astype('int')) \
.sort_index().reset_index() \
.rename(columns={
'is_spb': 'Административная единица',
'count': 'Относительная частота, %'}
).set_index('Административная единица') \
.rename(index={0: 'Область', 1: 'Город'}).T
| Административная единица | Область | Город |
|---|---|---|
| Относительная частота, % | 23 | 77 |
plt.title('Диаграмма распределения объявлений\nпо типу населённого пункта')
data['locality_type'].value_counts().plot.barh(figsize=(6, 3))
plt.xlabel('Количество объявлений')
plt.ylabel('Тип населённого пункта')
plt.show()
Таблица относительных частот.
pd.DataFrame((data['locality_type'].value_counts() /
data.shape[0] * 100).round(1)) \
.reset_index() \
.rename(columns={
'locality_type': 'Тип населённого пункта',
'count': 'Относительная частота, %'}
).set_index('Тип населённого пункта')
| Относительная частота, % | |
|---|---|
| Тип населённого пункта | |
| город | 84.7 |
| посёлок | 8.8 |
| деревня | 4.0 |
| городской посёлок | 2.3 |
| село | 0.1 |
| посёлок при железнодорожной станции | 0.1 |
urban = ((data['locality_type'] =='город') |
(data['locality_type'] == 'городской посёлок')).sum()
not_urban = data.shape[0] - urban
plt.title('Круговая диаграмма\nраспределения объявлений' +
'\nмежду городскими и сельскими\nнаселёнными пунктами')
pd.Series([urban, not_urban]).rename(
index={0: 'Городские\nнаселённые пункты',
1: 'Сельские\nнаселённые пункты'}
).plot.pie(figsize=(4, 4))
plt.show()
Количество уникальных наименований населённых пунктов.
len(data['locality_name'].unique())
298
Количество различных населённых пунктов Ленинградской области.
not_spb_unique_locality_number = pd.Series(
{type: len(data.loc[(~data['is_spb']) & (data['locality_type'] == type),
'locality_name'].unique())
for type in data['locality_type'].unique()})
not_spb_unique_locality_number.sum()
286
plt.title('Круговая диаграмма\nраспределения объявлений' +
'\nо продаже квартир в Ленинградской области' +
'\nпо типу населённого пункта')
not_spb_unique_locality_number.plot.pie(figsize=(4, 4))
plt.show()
Таблица относительных частот.
pd.DataFrame(not_spb_unique_locality_number) \
.reset_index() \
.rename(columns={
'index': 'Тип населённого пункта в Лен. обл.',
0: 'Частота'}
).set_index('Тип населённого пункта в Лен. обл.')
| Частота | |
|---|---|
| Тип населённого пункта в Лен. обл. | |
| город | 33 |
| деревня | 106 |
| посёлок | 97 |
| городской посёлок | 35 |
| посёлок при железнодорожной станции | 6 |
| село | 9 |
Количество населённых пунктов, расположенных в черте города Санкт-Петербурга.
in_spb_unique_locality_number = pd.Series(
{type: len(data.loc[(data['is_spb']) & (data['locality_type'] == type),
'locality_name'].unique())
for type in data['locality_type'].unique()})
in_spb_unique_locality_number.sum()
24
Различные населённые пункты, имеющие одинаковое наименование.
for name in list(data['locality_name'].sort_values().unique()):
type_list = list(data.loc[data['locality_name'] == name,
'locality_type'].unique())
if len(type_list) > 1:
print(name, '-', type_list)
Громово - ['посёлок', 'посёлок при железнодорожной станции'] Зимитицы - ['деревня', 'посёлок'] Калитино - ['деревня', 'посёлок'] Кудрово - ['деревня', 'город'] Любань - ['город', 'посёлок'] Мурино - ['посёлок', 'город'] Никольское - ['город', 'село'] Павлово - ['городской посёлок', 'село'] Рабитицы - ['деревня', 'посёлок'] Рябово - ['городской посёлок', 'посёлок'] Фёдоровское - ['деревня', 'городской посёлок'] Щеглово - ['посёлок', 'деревня']
plt.title('Круговая диаграмма\nраспределения объявлений' +
'\nпо наличию значения расстояния\nдо центра Санкт-Петербурга')
(data['city_centers_km'] > 0).value_counts().rename(
index={0: 'Нет', 1: 'Есть'}
).plot.pie(label='', figsize=(4, 4))
plt.show()
Таблица относительных частот.
pd.DataFrame((data['city_centers_km'] > 0).value_counts() /
data.shape[0] * 100).round(0).astype('int') \
.reset_index() \
.rename(columns={
'city_centers_km': 'Расстояние до центра Санкт-Петербурга',
'count': 'Относительная частота, %'}
).set_index('Расстояние до центра Санкт-Петербурга').rename(
index={0: 'не известно', 1: 'известно'}
).T
| Расстояние до центра Санкт-Петербурга | известно | не известно |
|---|---|---|
| Относительная частота, % | 77 | 23 |
descriptive_statistics(data.loc[data['city_centers_km'] > 0, 'city_centers_km'],
'Расстояние до центра Санкт-Петербурга, км')
| Расстояние до центра Санкт-Петербурга, км | |
|---|---|
| кол-во значений | 18087 |
| кол-во уникальных | 456 |
| мин. | 0.2 |
| -1.5IQR | 2.6 |
| 25 % | 9.3 |
| мода | [11.6] |
| медиана | 13.1 |
| среднее ариф. | 14.21 |
| 75 % | 16.3 |
| +1.5IQR | 23.6 |
| макс. | 66.0 |
| размах | 65.8 |
| межквартильный размах | 7.0 |
Количество значений, приходящихся на Санкт-Петербург.
data.loc[(data['is_spb']) & (data['city_centers_km'] > 0),
'city_centers_km'].count()
18080
plt.title('Диаграмма размаха\nраспределения объявлений по значению расстояния' +
'\nот квартиры до центра Санкт-Петербурга')
data.loc[data['city_centers_km'] > 0, 'city_centers_km'].plot.box(
vert=False,
xlabel='Расстояние до центра Санкт-Петербурга, км',
figsize=(10, 2))
plt.tick_params(left=False, labelleft=False)
plt.show()
plt.title('Диаграмма распределения объявлений' +
'\nпо значению расстояния от квартиры\nдо центра Санкт-Петербурга')
data.loc[data['city_centers_km'] > 0, 'city_centers_km'].plot.hist(
bins=[n + 1 for n in range(66)],
figsize=(15, 3))
plt.xlabel('Расстояние до центра Санкт-Петербурга, км')
plt.ylabel('Количество объявлений')
plt.show()
plt.title('Диаграмма распределения объявлений' +
'\nпо значению расстояния от квартиры\nдо центра Санкт-Петербурга')
data.loc[data['city_centers_km'] > 0, 'city_centers_km'].plot.hist(
bins=[0.05 * (n + 1) for n in range(1400)],
figsize=(15, 3))
plt.xlabel('Расстояние до центра Санкт-Петербурга, км')
plt.ylabel('Количество объявлений')
plt.show()
Топ-5 расстояний, наиболее распространённых в наборе данных.
pd.DataFrame(data.loc[data['city_centers_km'] > 0,
'city_centers_km'].value_counts()) \
.reset_index() \
.rename(columns={
'city_centers_km': 'Расстояние до центра Санкт-Петербурга, км',
'count': 'Относительная частота, %'}
).set_index('Расстояние до центра Санкт-Петербурга, км').head().T
| Расстояние до центра Санкт-Петербурга, км | 11.6 | 14.8 | 11.9 | 12.0 | 14.9 |
|---|---|---|---|---|---|
| Относительная частота, % | 226 | 221 | 186 | 185 | 182 |
не для всех объявлений известно расстояние от центра Санкт-Петербурга до объекта недвижимости
только 77 % всех объявлений содержат значение расстояния до центра Санкт-Петербурга — это 18 020 объявлений
почти все значения относятся к объектам, расположенным в городе Санкт-Петербурге
минимальное значение 200 м, максимальное — 66 км
модой является значение 14,8 км, её частота — 221
медиана — 13, среднее арифметическое значение — 14; располагаются рядом и не сильно отличаются от моды
распределение значений мультимодальное, с длинным "хвостом" справа
наблюдаются пики с максимумами при значениях 5 км, 12 км, 15 км, небольшая группа с максимумом при 31 км и отдельно расположенная группа значений с максимумом при 52 км
половина всех значений лежит в пределах 9—16 км
большинство значений укладывается в диапазон 2,6—23,6 км
plt.title('Круговая диаграмма\nраспределения объявлений' +
'\nпо наличию значения расстояния\nдо аэропорта')
(data['airports_km'] > 0).value_counts().rename(
index={0: 'Нет', 1: 'Есть'}
).plot.pie(label='', figsize=(4, 4))
plt.show()
Таблица относительных частот.
pd.DataFrame((data['airports_km'] > 0).value_counts() /
data.shape[0] * 100).round(0).astype('int') \
.reset_index() \
.rename(columns={
'airports_km': 'Расстояние до аэропорта',
'count': 'Относительная частота, %'}
).set_index('Расстояние до аэропорта').rename(
index={0: 'не известно', 1: 'известно'}
).T
| Расстояние до аэропорта | известно | не известно |
|---|---|---|
| Относительная частота, % | 77 | 23 |
descriptive_statistics(data.loc[data['airports_km'] > 0, 'airports_km'],
'Расстояние до аэропорта, км')
| Расстояние до аэропорта, км | |
|---|---|
| кол-во значений | 18020 |
| кол-во уникальных | 573 |
| мин. | 6.4 |
| -1.5IQR | -1.25 |
| 25 % | 18.6 |
| мода | [37.4] |
| медиана | 26.8 |
| среднее ариф. | 28.82 |
| 75 % | 37.3 |
| +1.5IQR | 54.85 |
| макс. | 84.9 |
| размах | 78.5 |
| межквартильный размах | 18.7 |
Количество значений, приходящихся на Санкт-Петербург.
data.loc[(data['is_spb']) & (data['airports_km'] > 0), 'airports_km'].count()
18013
plt.title('Диаграмма размаха\nраспределения объявлений по значению расстояния' +
'\nот квартиры до аэропорта')
data.loc[data['airports_km'] > 0, 'airports_km'].plot.box(
vert=False,
xlabel='Расстояние до аэропорта, км',
figsize=(10, 2))
plt.tick_params(left=False, labelleft=False)
plt.show()
plt.title('Диаграмма распределения объявлений' +
'\nпо значению расстояния от квартиры\nдо аэропорта')
data.loc[data['airports_km'] > 0, 'airports_km'].plot.hist(
bins=[n + 1 for n in range(66)],
figsize=(15, 3))
plt.xlabel('Расстояние до аэропорта, км')
plt.ylabel('Количество объявлений')
plt.show()
plt.title('Диаграмма распределения объявлений' +
'\nпо значению расстояния от квартиры\nдо аэропорта')
data.loc[data['airports_km'] > 0, 'airports_km'].plot.hist(
bins=[0.05 * (n + 1) for n in range(1400)],
figsize=(15, 3))
plt.xlabel('Расстояние до аэропорта, км')
plt.ylabel('Количество объявлений')
plt.show()
Топ-5 расстояний, наиболее распространённых в наборе данных.
pd.DataFrame(data.loc[data['airports_km'] > 0, 'airports_km'].value_counts()) \
.reset_index() \
.rename(columns={
'airports_km': 'Расстояние до аэропорта, км',
'count': 'Частота'}
).set_index('Расстояние до аэропорта, км').head().T
| Расстояние до аэропорта, км | 37.4 | 23.6 | 21.9 | 18.7 | 14.8 |
|---|---|---|---|---|---|
| Частота | 130 | 128 | 99 | 97 | 97 |
plt.title('Круговая диаграмма\nраспределения объявлений' +
'\nпо количеству ближайших парков')
data['parks_around_3000'].value_counts().sort_index().rename(
index={-1: 'Сведения\nотсутствуют', 0: 'Нет парков', 1: '1 парк',
2: '2 парка', 3: '3 парка'}
).plot.pie(label='', figsize=(4, 4))
plt.show()
Таблица относительных частот.
pd.DataFrame((data['parks_around_3000'].value_counts() /
data.shape[0] * 100).round(1).sort_index()) \
.reset_index() \
.rename(columns={
'parks_around_3000': 'Количество парков',
'count': 'Относительная частота, %'}
).set_index('Количество парков').rename(
index={-1: 'Отсутствуют сведения', 0: 'Нет парков', 1: '1 парк',
2: '2 парка', 3: '3 парка'}
).T
| Количество парков | Отсутствуют сведения | Нет парков | 1 парк | 2 парка | 3 парка |
|---|---|---|---|---|---|
| Относительная частота, % | 23.1 | 42.7 | 24.0 | 7.4 | 2.7 |
plt.title('Круговая диаграмма\nраспределения объявлений' +
'\nпо количеству ближайших парков\nдля тех объектов недвижимости,' +
'\nвокруг которых они есть')
data.loc[data['parks_around_3000'] > 0,
'parks_around_3000'].value_counts().sort_index().rename(
{1: '1 парк', 2: '2 парка', 3: '3 парка'}
).plot.pie(label='', figsize=(4, 4))
plt.show()
Таблица относительных частот.
pd.DataFrame((data.loc[data['parks_around_3000'] > 0,
'parks_around_3000'].value_counts() /
data[data['parks_around_3000'] > 0].shape[0] * 100).round(1).sort_index()) \
.reset_index() \
.rename(columns={
'parks_around_3000': 'Количество парков',
'count': 'Относительная частота, %'}
).set_index('Количество парков').rename(
index={1: '1 парк', 2: '2 парка', 3: '3 парка'}
).T
| Количество парков | 1 парк | 2 парка | 3 парка |
|---|---|---|---|
| Относительная частота, % | 70.4 | 21.6 | 8.0 |
descriptive_statistics(data.loc[data['parks_nearest'] > 0, 'parks_nearest'],
'Расстояние до ближайшего парка, м')
| Расстояние до ближайшего парка, м | |
|---|---|
| кол-во значений | 8007 |
| кол-во уникальных | 986 |
| мин. | 10 |
| -1.5IQR | -32.0 |
| 25 % | 288.0 |
| мода | [441] |
| медиана | 454.0 |
| среднее ариф. | 489.48 |
| 75 % | 612.0 |
| +1.5IQR | 940.0 |
| макс. | 2984 |
| размах | 2974 |
| межквартильный размах | 324.0 |
Количество значений, приходящихся на Санкт-Петербург.
data.loc[(data['is_spb']) & (data['parks_nearest'] > 0), 'parks_nearest'].count()
8007
plt.title('Диаграмма размаха\nраспределения объявлений' +
'\nпо значению расстояния до ближайшего парка')
data.loc[data['parks_nearest'] > 0, 'parks_nearest'].plot.box(
vert=False,
xlabel='Расстояние до парка, м',
figsize=(10, 2))
plt.tick_params(left=False, labelleft=False)
plt.show()
plt.title('Диаграмма распределения объявлений' +
'\nпо значению расстояния от квартиры\nдо ближайшего парка')
data.loc[data['parks_nearest'] > 0, 'parks_nearest'].plot.hist(
bins=[10 * (n + 1) for n in range(300)],
figsize=(15, 3))
plt.xlabel('Расстояние до парка, м')
plt.ylabel('Количество объявлений')
plt.show()
plt.title('Диаграмма распределения объявлений' +
'\nпо значению расстояния от квартиры\nдо ближайшего парка')
data.loc[data['parks_nearest'] > 0, 'parks_km'].plot.hist(
bins=[0.01 * (n + 1) for n in range(300)],
figsize=(15, 3))
plt.xlabel('Расстояние до парка, км')
plt.ylabel('Количество объявлений')
plt.show()
Топ-5 значений расстояний до ближайших парков (км).
pd.DataFrame(data.loc[data['parks_nearest'] > 0, 'parks_km'].value_counts()) \
.reset_index() \
.rename(columns={
'parks_km': 'Расстояние до парка, км',
'count': 'Частота'}
).set_index('Расстояние до парка, км').head().T
| Расстояние до парка, км | 0.5 | 0.4 | 0.6 | 0.3 | 0.2 |
|---|---|---|---|---|---|
| Частота | 1356 | 1316 | 1121 | 998 | 931 |
plt.title('Круговая диаграмма\nраспределения объявлений' +
'\nпо количеству ближайших водоёмов')
data['ponds_around_3000'].value_counts().sort_index().rename(
index={-1: 'Сведения\nотсутствуют', 0: 'Нет водоёмов', 1: '1 водоём',
2: '2 водоёма', 3: '3 водоёма'}
).plot.pie(label='', figsize=(4, 4))
plt.show()
Таблица относительных частот.
pd.DataFrame((data['ponds_around_3000'].value_counts() /
data.shape[0] * 100).round(1).sort_index()) \
.reset_index() \
.rename(columns={
'ponds_around_3000': 'Количество водоёмов',
'count': 'Относительная частота, %'}
).set_index('Количество водоёмов').rename(
index={-1: 'Сведения отсутствуют', 0: 'Нет водоёмов', 1: '1 водоём',
2: '2 водоёма', 3: '3 водоёма'}
).T
| Количество водоёмов | Сведения отсутствуют | Нет водоёмов | 1 водоём | 2 водоёма | 3 водоёма |
|---|---|---|---|---|---|
| Относительная частота, % | 23.1 | 38.3 | 24.2 | 8.0 | 6.3 |
plt.title('Круговая диаграмма\nраспределения объявлений' +
'\nпо количеству ближайших водоёмов\nдля тех объектов недвижимости,' +
'\nвокруг которых они есть')
data.loc[data['ponds_around_3000'] > 0,
'ponds_around_3000'].value_counts().sort_index().rename(
{1: '1 водоём', 2: '2 водоёма', 3: '3 водоёма'}
).plot.pie(label='', figsize=(4, 4))
plt.show()
Таблица относительных частот.
pd.DataFrame((data.loc[data['ponds_around_3000'] > 0,
'ponds_around_3000'].value_counts() /
data[data['ponds_around_3000'] > 0].shape[0] * 100).round(1).sort_index()) \
.reset_index() \
.rename(columns={
'ponds_around_3000': 'Количество водоёмов',
'count': 'Относительная частота, %'}
).set_index('Количество водоёмов').rename(
index={1: '1 водоём', 2: '2 водоёма', 3: '3 водоёма'}
).T
| Количество водоёмов | 1 водоём | 2 водоёма | 3 водоёма |
|---|---|---|---|
| Относительная частота, % | 62.9 | 20.7 | 16.5 |
descriptive_statistics(data.loc[data['ponds_nearest'] > 0, 'ponds_nearest'],
'Расстояние до ближайшего водоёма, м')
| Расстояние до ближайшего водоёма, м | |
|---|---|
| кол-во значений | 9033 |
| кол-во уникальных | 1096 |
| мин. | 13 |
| -1.5IQR | -152.0 |
| 25 % | 294.0 |
| мода | [427] |
| медиана | 502.0 |
| среднее ариф. | 518.02 |
| 75 % | 730.0 |
| +1.5IQR | 1156.0 |
| макс. | 1344 |
| размах | 1331 |
| межквартильный размах | 436.0 |
Количество значений, приходящихся на Санкт-Петербург.
data.loc[(data['is_spb']) & (data['ponds_nearest'] > 0), 'ponds_nearest'].count()
9031
plt.title('Диаграмма размаха\nраспределения объявлений' +
'\nпо значению расстояния до ближайшего водоёма')
data.loc[data['ponds_nearest'] > 0, 'ponds_nearest'].plot.box(
vert=False,
xlabel='Расстояние до водоёма, м',
figsize=(10, 2))
plt.tick_params(left=False, labelleft=False)
plt.show()
plt.title('Диаграмма распределения объявлений' +
'\nпо значению расстояния от квартиры\nдо ближайшего водоёма')
data.loc[data['ponds_nearest'] > 0, 'ponds_nearest'].plot.hist(
bins=[10 * (n + 1) for n in range(300)],
figsize=(15, 3))
plt.xlabel('Расстояние до ближайшего водоёма, м')
plt.ylabel('Количество объявлений')
plt.show()
plt.title('Диаграмма распределения объявлений' +
'\nпо значению расстояния от квартиры\nдо ближайшего водоёма')
data.loc[data['ponds_nearest'] > 0, 'ponds_km'].plot.hist(
bins=[0.01 * (n + 1) for n in range(300)],
figsize=(15, 3))
plt.xlabel('Расстояние до ближайшего водоёма, км')
plt.ylabel('Количество объявлений')
plt.show()
Топ-5 значений расстояний до ближайших водоёмов (км).
pd.DataFrame(data.loc[data['ponds_nearest'] > 0, 'ponds_km'].value_counts()) \
.reset_index() \
.rename(columns={
'ponds_km': 'Расстояние до водоёма, км',
'count': 'Частота'}
).set_index('Расстояние до водоёма, км').head().T
| Расстояние до водоёма, км | 0.4 | 0.5 | 0.6 | 0.2 | 0.7 |
|---|---|---|---|---|---|
| Частота | 1198 | 1050 | 1033 | 922 | 897 |
descriptive_statistics(data['floors_total'], 'Этажность зданий')
| Этажность зданий | |
|---|---|
| кол-во значений | 23439 |
| кол-во уникальных | 30 |
| мин. | 1 |
| -1.5IQR | -7.5 |
| 25 % | 5.0 |
| мода | [5] |
| медиана | 9.0 |
| среднее ариф. | 10.7 |
| 75 % | 16.0 |
| +1.5IQR | 25.5 |
| макс. | 35 |
| размах | 34 |
| межквартильный размах | 11.0 |
plt.title('Диаграмма распределения объявлений' +
'\nпо этажности здания, в котором расположен объект недвижимости')
data['floors_total'].value_counts().sort_index().plot.bar(rot=0, figsize=(10, 3))
plt.xlabel('Этажность здания')
plt.ylabel('Количество объявлений')
plt.show()
Топ-7 этажностей зданий.
pd.DataFrame(data['floors_total'].value_counts()) \
.reset_index() \
.rename(columns={
'floors_total': 'Этажность здания',
'count': 'Частота'}
).set_index('Этажность здания').head(7).T
| Этажность здания | 5 | 9 | 16 | 12 | 4 | 10 | 25 |
|---|---|---|---|---|---|---|---|
| Частота | 5735 | 3736 | 1360 | 1353 | 1186 | 1168 | 1080 |
floors_5 = (data['floors_total'] <= 5).sum()
floors_9 = ((data['floors_total'] > 5) & (data['floors_total'] <= 9)).sum()
floors_16 = ((data['floors_total'] > 9) & (data['floors_total'] <= 16)).sum()
floors_35 = ((data['floors_total'] > 16) & (data['floors_total'] <= 35)).sum()
plt.title('Круговая диаграмма\nраспределения объявлений\nпо этажности здания,' +
'\nв котором расположен объект недвижимости')
floors_category = pd.Series({'1—5 эт.': floors_5,
'6—9 эт.': floors_9,
'10—16 эт.': floors_16,
'16—35 эт.': floors_35})
floors_category.plot.pie(figsize=(4, 4))
plt.show()
Таблица относительных частот.
pd.DataFrame(floors_category/len(data)*100).round(0).astype('int') \
.reset_index() \
.rename(columns={
'index': 'Этажность здания',
0: 'Относительная частота, %'}
).set_index('Этажность здания').T
| Этажность здания | 1—5 эт. | 6—9 эт. | 10—16 эт. | 16—35 эт. |
|---|---|---|---|---|
| Относительная частота, % | 34 | 24 | 22 | 20 |
plt.title('Круговая диаграмма\nраспределения объявлений' +
'\nпо типу этажа, на котором\nрасположен объект недвижимости')
data['floor_type'].value_counts().plot.pie(label='', figsize=(4, 4))
plt.show()
Таблица относительных частот.
pd.DataFrame((data['floor_type'].value_counts() /
data.shape[0] * 100).round(0).astype('int')) \
.reset_index() \
.rename(columns={
'floor_type': 'Тип этажа',
'count': 'Относительная частота, %'}
).set_index('Тип этажа').T
| Тип этажа | другой | последний | первый |
|---|---|---|---|
| Относительная частота, % | 74 | 14 | 12 |
plt.title('Диаграмма рапределения объявлений' +
'\nпо номеру этажа, на котором расположен объект недвижимости')
data['floor'].value_counts().sort_index().plot.bar(rot=0, figsize=(10, 3))
plt.xlabel('Номер этажа')
plt.ylabel('Количество объявлений')
plt.show()
plt.title('Диаграмма рапределения объявлений\nпо количеству комнат в квартире')
data['rooms'].value_counts().sort_index().plot.bar(rot=0, figsize=(10, 3))
plt.xlabel('Количество комнат')
plt.ylabel('Количество объявлений')
plt.show()
Таблица частот.
pd.DataFrame(data['rooms'].value_counts().sort_index()) \
.reset_index() \
.rename(columns={
'rooms': 'Количество комнат',
'count': 'Частота'}
).set_index('Количество комнат').T
| Количество комнат | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 15 | 16 | 19 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Частота | 8114 | 7865 | 5766 | 1175 | 324 | 104 | 60 | 12 | 8 | 3 | 2 | 1 | 2 | 1 | 1 | 1 |
rooms_category = pd.Series({
'1-комн. кв.': (data['rooms'] == 1).sum(),
'2-комн. кв.': (data['rooms'] == 2).sum(),
'3-комн. кв.': (data['rooms'] == 3).sum(),
'4-комн. кв.': (data['rooms'] == 4).sum(),
'(5+)-комн. кв.': (data['rooms'] >= 5).sum()
})
plt.title('Круговая диаграмма\nрапределения квартир по количеству комнат')
rooms_category.plot.pie(figsize=(4, 4))
plt.show()
Таблица относительных частот.
pd.DataFrame(rooms_category / len(data) * 100).round(1) \
.reset_index() \
.rename(columns={
'index': 'Квартира',
0: 'Относительная частота, %'}
).set_index('Квартира').T
| Квартира | 1-комн. кв. | 2-комн. кв. | 3-комн. кв. | 4-комн. кв. | (5+)-комн. кв. |
|---|---|---|---|---|---|
| Относительная частота, % | 34.6 | 33.6 | 24.6 | 5.0 | 2.2 |
descriptive_statistics(data['total_area'], 'Общая площадь, м$^2$')
| Общая площадь, м$^2$ | |
|---|---|
| кол-во значений | 23439 |
| кол-во уникальных | 2159 |
| мин. | 13.0 |
| -1.5IQR | 7.0 |
| 25 % | 40.0 |
| мода | [45.0] |
| медиана | 52.0 |
| среднее ариф. | 60.44 |
| 75 % | 70.0 |
| +1.5IQR | 97.0 |
| макс. | 900.0 |
| размах | 887.0 |
| межквартильный размах | 30.0 |
plt.title('Диаграмма размаха\nраспределения объявлений' +
'\nпо значению общей площади объекта недвижимости')
data['total_area'].plot.box(
vert=False,
xlabel='Общая площадь, м$^2$',
figsize=(10, 2))
plt.tick_params(left=False, labelleft=False)
plt.show()
Топ-10 значений общей площади объектов недвижимости.
pd.DataFrame(data['total_area'].value_counts()) \
.reset_index() \
.rename(columns={
'total_area': 'Общая площадь, м$^2$',
'count': 'Частота'}
).set_index('Общая площадь, м$^2$').head(10).T
| Общая площадь, м$^2$ | 45.0 | 42.0 | 60.0 | 31.0 | 44.0 | 40.0 | 43.0 | 32.0 | 46.0 | 36.0 |
|---|---|---|---|---|---|---|---|---|---|---|
| Частота | 414 | 380 | 343 | 342 | 341 | 310 | 299 | 285 | 278 | 278 |
plt.title('Диаграмма распределения объявлений' +
'\nпо значению общей площади объекта недвижимости')
data['total_area'].plot.hist(bins=[n + 1 for n in range(900)], figsize=(10, 3))
plt.xlabel('Общая площадь, м$^2$')
plt.ylabel('Количество объявлений')
plt.show()
plt.title('Диаграмма распределения объявлений' +
'\nпо значениям общей площади объекта недвижимости,' +
'\nпопадающим в размах "усов" на диаграмме размаха')
data.loc[data['total_area'] <= data['total_area'].median() +
1.5 * (data['total_area'].quantile(q=.75) -
data['total_area'].quantile(q=.25)),
'total_area'].plot.hist(bins=[1 * (n + 1) for n in range(100)],
figsize=(10, 3))
plt.xlabel('Общая площадь, м$^2$')
plt.ylabel('Количество объявлений')
plt.show()
plt.title('Диаграмма распределения объявлений' +
'\nпо значениям общей площади объекта недвижимости,' +
'\nпопадающим в размах "усов" на диаграмме размаха')
data.loc[data['total_area'] <= data['total_area'].median() +
1.5 * (data['total_area'].quantile(q=.75) -
data['total_area'].quantile(q=.25)),
'total_area'].plot.hist(bins=[0.1 * (n + 1) for n in range(1000)],
figsize=(15, 5),
xticks=[10*m for m in range(11)])
plt.xlabel('Общая площадь, м$^2$')
plt.ylabel('Количество объявлений')
plt.show()
plt.title('Диаграмма распределения объявлений' +
'\nпо значению общей площади объектов недвижимости,' +
'\nсгруппированных по количеству комнат')
data.groupby('rooms')['total_area'].plot.hist(
bins=[1 * (n + 1) for n in range(200)],
alpha=0.5,
figsize=(10, 3))
plt.xlabel('Общая площадь, м$^2$')
plt.ylabel('Количество объявлений')
plt.show()
descriptive_statistics(data['living_area'], 'Жилая площадь, м$^2$')
| Жилая площадь, м$^2$ | |
|---|---|
| кол-во значений | 23439 |
| кол-во уникальных | 2001 |
| мин. | 6.0 |
| -1.5IQR | -5.7 |
| 25 % | 18.5 |
| мода | [18.0] |
| медиана | 30.0 |
| среднее ариф. | 34.25 |
| 75 % | 42.3 |
| +1.5IQR | 65.7 |
| макс. | 409.7 |
| размах | 403.7 |
| межквартильный размах | 23.8 |
plt.title('Диаграмма размаха\nраспределения объявлений' +
'\nпо значению жилой площади объекта недвижимости')
data['living_area'].plot.box(
vert=False,
xlabel='Жилая площадь, м$^2$',
figsize=(10, 2))
plt.tick_params(left=False, labelleft=False)
plt.show()
plt.title('Диаграмма распределения объявлений' +
'\nпо значению жилой площади объекта недвижимости')
data['living_area'].plot.hist(
bins=[n + 1 for n in range(400)],
figsize=(15, 3))
plt.xlabel('Жилая площадь, м$^2$')
plt.ylabel('Количество объявлений')
plt.show()
plt.title('Диаграмма распределения объявлений' +
'\nпо значениям общей площади объекта недвижимости,' +
'\nпопадающим в размах "усов" на диаграмме размаха')
data.loc[data['living_area'] <= data['living_area'].median() +
1.5 * (data['living_area'].quantile(q=.75) -
data['living_area'].quantile(q=.25)),
'living_area'].plot.hist(bins=[n + 1 for n in range(70)],
figsize=(10, 3))
plt.xlabel('Жилая площадь, м$^2$')
plt.ylabel('Количество объявлений')
plt.show()
plt.title('Диаграмма распределения объявлений' +
'\nпо значениям общей площади объекта недвижимости,' +
'\nпопадающим в размах "усов" на диаграмме размаха')
data.loc[data['living_area'] <= data['living_area'].median() +
1.5 * (data['living_area'].quantile(q=.75) -
data['living_area'].quantile(q=.25)),
'living_area'].plot.hist(bins=[0.1 * (n + 1) for n in range(700)],
figsize=(10, 3))
plt.xlabel('Жилая площадь, м$^2$')
plt.ylabel('Количество объявлений')
plt.show()
plt.title('Диаграмма распределения объявлений' +
'\nпо значению жилой площади объектов недвижимости,' +
'\nсгруппированных по количеству комнат')
data.groupby('rooms')['living_area'].plot.hist(bins=[(n + 1) for n in range(100)],
alpha=0.5,
figsize=(10, 3))
plt.xlabel('Жилая площадь, м$^2$')
plt.ylabel('Количество объявлений')
plt.show()
Описательная статистика значений площади, приходящихся в среднем на одну жилую комнату.
descriptive_statistics(data['living_area'] / data['rooms'],
'Площадь жилой комнаты, м$^2$')
| Площадь жилой комнаты, м$^2$ | |
|---|---|
| кол-во значений | 23439 |
| кол-во уникальных | 2036 |
| мин. | 4.0 |
| -1.5IQR | 10.75 |
| 25 % | 14.5 |
| мода | [18.0] |
| медиана | 16.0 |
| среднее ариф. | 16.58 |
| 75 % | 18.0 |
| +1.5IQR | 21.25 |
| макс. | 62.5 |
| размах | 58.5 |
| межквартильный размах | 3.5 |
plt.title('Диаграмма распределения объявлений\nпо среднему значению площади,' +
'\nприходящейся на одну жилую комнату')
(data['living_area']/data['rooms']).plot.hist(bins=[n + 1 for n in range(63)])
plt.xlabel('Площадь жилой комнаты, м$^2$')
plt.ylabel('Количество объявлений')
plt.show()
descriptive_statistics(data['kitchen_area'], 'Площадь кухни, м$^2$')
| Площадь кухни, м$^2$ | |
|---|---|
| кол-во значений | 23439 |
| кол-во уникальных | 1211 |
| мин. | 2.0 |
| -1.5IQR | 1.66 |
| 25 % | 7.0 |
| мода | [6.0] |
| медиана | 9.01 |
| среднее ариф. | 10.39 |
| 75 % | 11.9 |
| +1.5IQR | 16.36 |
| макс. | 112.0 |
| размах | 110.0 |
| межквартильный размах | 4.9 |
plt.title('Диаграмма размаха\nраспределения объявлений' +
'\nпо значению площади кухни объекта недвижимости')
data['kitchen_area'].plot.box(
vert=False,
xlabel='Площадь кухни, м$^2$',
figsize=(10, 2))
plt.tick_params(left=False, labelleft=False)
plt.show()
plt.title('Диаграмма распределения объявлений' +
'\nпо значению площади кухни объекта недвижимости')
data['kitchen_area'].plot.hist(bins=[1 * (n + 1) for n in range(125)],
figsize=(15, 3))
plt.xlabel('Площадь кухни, м$^2$')
plt.ylabel('Количество объявлений')
plt.show()
plt.title('Диаграмма распределения объявлений' +
'\nпо значениям площади кухни объекта недвижимости,' +
'\nпопадающим в размах "усов" на диаграмме размаха')
data.loc[data['kitchen_area'] <= data['kitchen_area'].median() +
1.5 * (data['kitchen_area'].quantile(q=.75) -
data['kitchen_area'].quantile(q=.25)),
'kitchen_area'].plot.hist(bins=[0.05 * (n + 1) for n in range(400)],
figsize=(10, 3),
xticks=[2*m for m in range(11)])
plt.xlabel('Площадь кухни, м$^2$')
plt.ylabel('Количество объявлений')
plt.show()
Топ-10 значений площади кухни.
pd.DataFrame(data['kitchen_area'].value_counts()) \
.reset_index() \
.rename(columns={
'kitchen_area': 'Площадь кухни, м$^2$',
'count': 'Частота'}
).set_index('Площадь кухни, м$^2$').head(10).T
| Площадь кухни, м$^2$ | 6.0 | 10.0 | 8.0 | 9.0 | 7.0 | 11.0 | 12.0 | 8.5 | 5.0 | 5.5 |
|---|---|---|---|---|---|---|---|---|---|---|
| Частота | 1298 | 1248 | 1115 | 1092 | 1070 | 791 | 653 | 417 | 414 | 407 |
plt.title('Диаграмма распределения объявлений' +
'\nпо значению площади кухни объектов недвижимости,' +
'\nсгруппированных по количеству комнат')
data.groupby('rooms')['kitchen_area'].plot.hist(bins=[n + 1 for n in range(30)],
alpha=0.5)
plt.xlabel('Площадь кухни, м$^2$')
plt.ylabel('Количество объявлений')
plt.show()
plt.title('Диаграмма распределения объявлений' +
'\nпо количеству балконов у объектов недвижимости')
data['balcony'].value_counts().sort_index().plot.bar(rot=0, figsize=(6, 3))
plt.xlabel('Количество балконов')
plt.ylabel('Количество объявлений')
plt.show()
pd.DataFrame((data['balcony'].value_counts() / data.shape[0] * 100).round(1)) \
.reset_index() \
.rename(columns={
'balcony': 'Количество балконов',
'count': 'Относительная частота, %'}
).set_index('Количество балконов').T
| Количество балконов | 0 | 1 | 2 | 5 | 4 | 3 |
|---|---|---|---|---|---|---|
| Относительная частота, % | 64.5 | 17.7 | 15.4 | 1.3 | 0.8 | 0.3 |
descriptive_statistics(data['ceiling_height'], 'Высота потолков, м')
| Высота потолков, м | |
|---|---|
| кол-во значений | 23439 |
| кол-во уникальных | 167 |
| мин. | 2.0 |
| -1.5IQR | 2.26 |
| 25 % | 2.5 |
| мода | [2.5] |
| медиана | 2.65 |
| среднее ариф. | 2.7 |
| 75 % | 2.76 |
| +1.5IQR | 3.04 |
| макс. | 6.0 |
| размах | 4.0 |
| межквартильный размах | 0.26 |
plt.title('Диаграмма размаха\nраспределения объявлений' +
'\nпо значению высоты потолка объекта недвижимости')
data['ceiling_height'].plot.box(
vert=False,
xlabel='Высота потолка, м',
figsize=(10, 2))
plt.tick_params(left=False, labelleft=False)
plt.show()
plt.title('Диаграмма распределения объявлений' +
'\nпо значению высоты потолка у объектов недвижимости')
data['ceiling_height'].plot.hist(bins=[0.01 * (n + 1) + 2 for n in range(400)],
figsize=(15, 3))
plt.xlabel('Высота потолков, м')
plt.ylabel('Количество объявлений')
plt.show()
Топ-7 значений высоты потолка.
pd.DataFrame((data['ceiling_height'].value_counts() /
data.shape[0] * 100)).round(0).astype('int') \
.reset_index() \
.rename(columns={
'ceiling_height': 'Высота потолка, м',
'count': 'Относительная частота, %'}
).set_index('Высота потолка, м').head(7).T
| Высота потолка, м | 2.50 | 2.70 | 2.60 | 3.00 | 2.75 | 2.80 | 2.55 |
|---|---|---|---|---|---|---|---|
| Относительная частота, % | 31 | 13 | 10 | 9 | 8 | 7 | 5 |
plt.title('Круговая диаграмма распределения объявлений' +
'\nпо факту того, является ли квартира студией')
data['studio'].astype('int').value_counts().rename(
index={0: 'Не студия', 1: 'Студия'}
).plot.pie(label='', figsize=(4, 4))
plt.show()
pd.DataFrame((data['studio'].astype('int').value_counts() /
data.shape[0] * 100)).round(1) \
.reset_index() \
.rename(columns={
'studio': 'Является ли квартира студией',
'count': 'Относительная частота, %'}
).set_index('Является ли квартира студией').rename(
index={0: 'Не студия', 1: 'Студия'}
).T
| Является ли квартира студией | Не студия | Студия |
|---|---|---|
| Относительная частота, % | 99.1 | 0.9 |
plt.title('Круговая диаграмма распределения объявлений' +
'\nпо факту того, является ли квартира апартаментами')
data['is_apartment'].astype('int').value_counts().rename(
index={0: 'Не апартаменты', 1: 'Апартаменты'}
).plot.pie(label='', figsize=(4, 4))
plt.show()
pd.DataFrame((data['is_apartment'].astype('int').value_counts() /
data.shape[0] * 100)).round(1) \
.reset_index() \
.rename(columns={
'is_apartment': 'Является ли квартира апартаментами',
'count': 'Относительная частота, %'}
).set_index('Является ли квартира апартаментами').rename(
index={0: 'Не апартаменты', 1: 'Апартаменты'}
).T
| Является ли квартира апартаментами | Не апартаменты | Апартаменты |
|---|---|---|
| Относительная частота, % | 99.8 | 0.2 |
descriptive_statistics(data['last_price'], 'Цена объекта, руб.')
| Цена объекта, руб. | |
|---|---|
| кол-во значений | 23439 |
| кол-во уникальных | 2955 |
| мин. | 12190 |
| -1.5IQR | -390000.0 |
| 25 % | 3440000.0 |
| мода | [4500000] |
| медиана | 4650000.0 |
| среднее ариф. | 6551914.3 |
| 75 % | 6800000.0 |
| +1.5IQR | 9690000.0 |
| макс. | 763000000 |
| размах | 762987810 |
| межквартильный размах | 3360000.0 |
plt.title('Диаграмма размаха' +
'\nраспределения объявлений по цене объекта недвижимости')
data['last_price'].plot.box(
vert=False,
xlabel='Цена объекта, руб.',
figsize=(10, 2))
plt.tick_params(left=False, labelleft=False)
plt.show()
plt.title('Диаграмма распределения объявлений\nпо цене объекта недвижимости')
data['last_price'].plot.hist(
bins=[100000 * (n + 1) for n in range(300)],
figsize=(10, 3))
plt.xlabel('Цена объекта, руб.')
plt.ylabel('Количество объявлений')
plt.show()
plt.title('Диаграмма распределения объявлений\nпо цене объекта недвижимости')
data['last_price'].plot.hist(
bins=[10000 * (n + 1) for n in range(3000)],
figsize=(10, 3))
plt.xlabel('Цена объекта, руб.')
plt.ylabel('Количество объявлений')
plt.show()
Топ-10 значений цены объекта по распространённости.
pd.DataFrame(data['last_price'].value_counts()) \
.reset_index() \
.rename(columns={
'last_price': 'Цена квартиры, руб.',
'count': 'Частота'}
).set_index('Цена квартиры, руб.').head(10).T
| Цена квартиры, руб. | 4500000 | 3500000 | 4200000 | 4300000 | 4000000 | 3600000 | 3300000 | 3800000 | 3200000 | 4100000 |
|---|---|---|---|---|---|---|---|---|---|---|
| Частота | 339 | 287 | 259 | 258 | 257 | 256 | 240 | 238 | 237 | 231 |
descriptive_statistics(data['price_per_square_meter'],
'Цена за квадратный метр, руб.')
| Цена за квадратный метр, руб. | |
|---|---|
| кол-во значений | 23439 |
| кол-во уникальных | 14195 |
| мин. | 112 |
| -1.5IQR | 38749.25 |
| 25 % | 76635.0 |
| мода | [100000] |
| медиана | 95000.0 |
| среднее ариф. | 99365.74 |
| 75 % | 114135.5 |
| +1.5IQR | 151250.75 |
| макс. | 1907500 |
| размах | 1907388 |
| межквартильный размах | 37500.5 |
plt.title('Диаграмма размаха' +
'\nраспределения объявлений по цене одного квадратного метра')
data['price_per_square_meter'].plot.box(
vert=False,
xlabel='Цена квадратного метра, руб.',
figsize=(10, 2))
plt.tick_params(left=False, labelleft=False)
plt.show()
plt.title('Диаграмма распределения объявлений' +
'\nпо цене одного квадратного метра')
data['price_per_square_meter'].plot.hist(
bins=[1000 * (n + 1) for n in range(200)],
figsize=(10, 3))
plt.xlabel('Цена квадратного метра, руб.')
plt.ylabel('Количество объявлений')
plt.show()
Топ-10 значений цены за квадратный метр.
pd.DataFrame(data['price_per_square_meter'].value_counts()) \
.reset_index() \
.rename(columns={
'price_per_square_meter': 'Цена квадратного метра, руб.',
'count': 'Частота'}
).set_index('Цена квадратного метра, руб.').head(10).T
| Цена квадратного метра, руб. | 100000 | 83333 | 75000 | 125000 | 66667 | 80000 | 90000 | 50000 | 116667 | 90909 |
|---|---|---|---|---|---|---|---|---|---|---|
| Частота | 261 | 69 | 59 | 52 | 52 | 51 | 47 | 47 | 37 | 37 |
descriptive_statistics(data['total_images'], 'Количество фотографий')
| Количество фотографий | |
|---|---|
| кол-во значений | 23439 |
| кол-во уникальных | 38 |
| мин. | 0 |
| -1.5IQR | -3.0 |
| 25 % | 6.0 |
| мода | [10] |
| медиана | 9.0 |
| среднее ариф. | 9.86 |
| 75 % | 14.0 |
| +1.5IQR | 21.0 |
| макс. | 50 |
| размах | 50 |
| межквартильный размах | 8.0 |
plt.title('Диаграмма распределения объявлений\nпо количеству фотографий')
data['total_images'].plot.hist(bins=[n for n in range(51)])
plt.xlabel('Количество фотографий')
plt.ylabel('Количество объявлений')
plt.show()
Топ-5 количества фотографий.
pd.DataFrame(data['total_images'].value_counts()) \
.reset_index() \
.rename(columns={
'total_images': 'Количество фотографий',
'count': 'Частота'}
).set_index('Количество фотографий').head().T
| Количество фотографий | 10 | 9 | 20 | 8 | 7 |
|---|---|---|---|---|---|
| Частота | 1780 | 1701 | 1679 | 1569 | 1506 |
plt.title('Тепловая карта\nматрицы корреляции' +
'\nзначений количественных признаков')
sns.heatmap(data[[
'last_price', 'price_per_square_meter', 'total_area', 'living_area',
'kitchen_area', 'ceiling_height', 'city_centers_nearest',
'airports_nearest', 'parks_nearest', 'ponds_nearest', 'days_exposition'
]].corr())
plt.show()
plt.title('Тепловая карта\nматрицы корреляции' +
'\nзначений категориальных признаков' +
'\n(и признаков, представленных как категориальные)')
sns.heatmap(data[[
'last_price', 'price_per_square_meter', 'total_area', 'living_area',
'kitchen_area', 'ceiling_height', 'city_centers_nearest',
'airports_nearest', 'parks_nearest', 'ponds_nearest', 'days_exposition',
'rooms', 'balcony', 'floor', 'floors_total', 'parks_around_3000',
'ponds_around_3000', 'year', 'month', 'weekday', 'total_images'
]].corr(method='kendall'))
plt.show()
Топ-10 населённых пунктов с наибольшим числом объявлений (в соответствии с перечнем населённых пунктов, указанных в наборе данных).
pd.DataFrame([
data['locality_name'].value_counts(),
data.groupby('locality_name')['price_per_square_meter'].mean().round(0).astype('int')
]).T.head(10) \
.reset_index().rename(
columns={'locality_name': '',
'count': 'Количество объявлений',
'price_per_square_meter': 'Цена за квадратный метр, руб.'}) \
.set_index('')
| Количество объявлений | Цена за квадратный метр, руб. | |
|---|---|---|
| Санкт-Петербург | 15608 | 114670 |
| Мурино | 577 | 85809 |
| Кудрово | 465 | 95202 |
| Шушары | 437 | 78549 |
| Всеволожск | 390 | 68473 |
| Пушкин | 370 | 102969 |
| Колпино | 337 | 75481 |
| Парголово | 325 | 90069 |
| Гатчина | 303 | 68625 |
| Выборг | 233 | 58345 |
Топ-10 населённых пунктов с наибольшим числом объявлений (в соответствии с административно-территориальным делением).
pd.DataFrame([
data.loc[data['is_spb'] == False, 'locality_name'].value_counts(),
data.loc[data['is_spb'] == False].groupby('locality_name') \
['price_per_square_meter'].mean().round(0).astype('int')]).rename(
index={'count': 'Количество объявлений',
'price_per_square_meter': 'Цена квадратного метра, руб.'}
).join(pd.DataFrame({
'Санкт-Петербург': [
data['is_spb'].sum(),
data.loc[data['is_spb'], 'price_per_square_meter'].mean().round(0).astype('int')
]
}).rename(index={0: 'Количество объявлений',
1: 'Цена квадратного метра, руб.'})
).T.sort_values(by='Количество объявлений',
ascending=False).head(10)
| Количество объявлений | Цена квадратного метра, руб. | |
|---|---|---|
| Санкт-Петербург | 18080 | 110640 |
| Мурино | 577 | 85809 |
| Кудрово | 465 | 95202 |
| Всеволожск | 390 | 68473 |
| Гатчина | 303 | 68625 |
| Выборг | 233 | 58345 |
| Новое Девяткино | 141 | 75860 |
| Сертолово | 141 | 69319 |
| Кириши | 124 | 38642 |
| Бугры | 112 | 80512 |
Согласно перечню населённых пунктов набора данных:
Согласно административно-территориальному делению:
data['city_centers_km_int'] = (data['city_centers_nearest'] / 1000).round(0)
plt.title('График зависимости\nсредней стоимости объекта недвижимости' +
'\nот расстояния до центра Санкт-Петербурга')
data[data['is_spb']].groupby('city_centers_km_int')['last_price'].mean().plot(
figsize=(6, 4))
plt.xlabel('Расстояние до центра, км')
plt.ylabel('Средняя стоимость объекта, руб.')
plt.show()
Топ-15 самых дорогих километров от центра.
pd.DataFrame(data[data['is_spb']].groupby('city_centers_km_int') \
['last_price'].mean().sort_values(ascending=False)).head(15) \
.reset_index().rename(
columns={'city_centers_km_int': 'Расстояние до центра, км',
'last_price': 'Средняя стоимость объекта, руб.'})
| Расстояние до центра, км | Средняя стоимость объекта, руб. | |
|---|---|---|
| 0 | 1.0 | 2.130401e+07 |
| 1 | 0.0 | 1.926459e+07 |
| 2 | 2.0 | 1.791487e+07 |
| 3 | 6.0 | 1.538862e+07 |
| 4 | 7.0 | 1.483441e+07 |
| 5 | 5.0 | 1.450482e+07 |
| 6 | 4.0 | 1.329379e+07 |
| 7 | 43.0 | 1.153148e+07 |
| 8 | 3.0 | 1.111668e+07 |
| 9 | 8.0 | 9.928107e+06 |
| 10 | 55.0 | 9.000000e+06 |
| 11 | 9.0 | 6.927587e+06 |
| 12 | 10.0 | 6.510731e+06 |
| 13 | 54.0 | 6.273150e+06 |
| 14 | 11.0 | 6.258976e+06 |
data.plot.scatter(
x='total_area',
y='last_price',
xlabel='Общая площадь, м$^2$',
ylabel='Цена объекта, руб.',
title='Диаграмма рассеяния\nзначений цены объекта недвижимости' +
'\nпо значениям общей площади',
alpha=0.2,
figsize=(10, 3))
plt.show()
Коэффициент корреляции.
data['last_price'].corr(data['total_area']).round(2)
0.65
plt.title('График зависимости\nсредней стоимости объекта от общей площади')
data.groupby('total_area')['last_price'].mean().plot(figsize=(10, 3))
plt.xlabel('Общая площадь, м$^2$')
plt.ylabel('Средняя стоимость\nобъекта, руб.')
plt.show()
plt.title('График зависимости' +
'\nсредней стоимости объекта от общей площади для значений,' +
'\nпопадающих в размах "усов" на диаграмме размаха')
data[(data['last_price'] <= data['last_price'].median() +
1.5 * (data['last_price'].quantile(q=.75) -
data['last_price'].quantile(q=.25))) &
(data['total_area'] <= data['total_area'].median() +
1.5 * (data['total_area'].quantile(q=.75) -
data['total_area'].quantile(q=.25)))
].groupby('total_area')['last_price'].mean().plot(figsize=(10, 3))
plt.xlabel('Общая площадь, м$^2$')
plt.ylabel('Средняя стоимость\nобъекта, руб.')
plt.show()
data.plot.scatter(
x='living_area',
y='last_price',
xlabel='Жилая площадь, м$^2$',
ylabel='Цена объекта, руб.',
title='Диаграмма рассеяния\nзначений цены объекта недвижимости' +
'\nпо значениям жилой площади',
alpha=0.2,
figsize=(10, 3))
plt.show()
Коэффициент корреляции.
data['last_price'].corr(data['living_area']).round(2)
0.56
plt.title('График зависимости' +
'\nсредней стоимости объекта недвижимости от жилой площади')
data.groupby('living_area')['last_price'].mean().plot(figsize=(10, 3))
plt.xlabel('Жилая площадь, м$^2$')
plt.ylabel('Средняя стоимость\nобъекта, руб.')
plt.show()
plt.title('График зависимости\nсредней стоимости объекта от жилой площади' +
'\nдля значений, попадающих в размах "усов" на диаграмме размаха')
data.loc[(data['last_price'] <= data['last_price'].median() +
1.5 * (data['last_price'].quantile(q=.75) -
data['last_price'].quantile(q=.25))) &
(data['living_area'] <= data['living_area'].median() +
1.5 * (data['living_area'].quantile(q=.75) -
data['living_area'].quantile(q=.25)))
].groupby('living_area')['last_price'].mean().plot(figsize=(10, 3))
plt.xlabel('Жилая площадь, м$^2$')
plt.ylabel('Средняя стоимость\nобъекта, руб.')
plt.show()
data.plot.scatter(
x='kitchen_area',
y='last_price',
xlabel='Площадь кухни, м$^2$',
ylabel='Цена объекта, руб.',
title='Диаграмма рассеяния\nзначений цены объекта недвижимости' +
'\nпо значениям площади кухни',
alpha=0.2,
figsize=(10, 3))
plt.show()
Коэффициент корреляции.
data['last_price'].corr(data['kitchen_area']).round(2)
0.46
plt.title('График зависимости' +
'\nсредней стоимости объекта недвижимости от площади кухни')
data.groupby('kitchen_area')['last_price'].mean().plot(figsize=(10, 3))
plt.xlabel('Площадь кухни, м$^2$')
plt.ylabel('Средняя стоимость\nобъекта, руб.')
plt.show()
plt.title('График зависимости\nсредней стоимости объекта от площади кухни' +
'\nдля значений, попадающих в размах "усов" на диаграмме размаха')
data.loc[(data['last_price'] <= data['last_price'].median() +
1.5 * (data['last_price'].quantile(q=.75) -
data['last_price'].quantile(q=.25))) &
(data['kitchen_area'] <= data['kitchen_area'].median() +
1.5 * (data['kitchen_area'].quantile(q=.75) -
data['kitchen_area'].quantile(q=.25)))
].groupby('kitchen_area')['last_price'].mean().plot(figsize=(10, 3))
plt.xlabel('Площадь кухни, м$^2$')
plt.ylabel('Средняя стоимость\nобъекта, руб.')
plt.show()
data.plot.scatter(
x='rooms',
y='last_price',
xlabel='Количество комнат',
ylabel='Цена объекта, руб.',
title='Диаграмма рассеяния\nзначений цены объекта недвижимости' +
'\nпо значениям количества комнат',
xticks=[n + 1 for n in range(19)],
alpha=0.2,
figsize=(10, 3))
plt.show()
Коэффициент корреляции.
data['last_price'].corr(data['rooms'], method='kendall').round(2)
0.42
plt.title('График зависимости' +
'\nсредней стоимости объекта от количества жилых комнат')
data.groupby('rooms')['last_price'].mean().plot(
xticks=[n + 1 for n in range(19)],
figsize=(10, 3))
plt.xlabel('Количество комнат')
plt.ylabel('Средняя стоимость\nобъекта, руб.')
plt.show()
plt.title('График зависимости' +
'\nсредней стоимости объекта от количества жилых комнат' +
'\nдля значений, попадающих в размах "усов" на диаграмме размаха')
data[(data['last_price'] <= data['last_price'].median() +
1.5 * (data['last_price'].quantile(q=.75) -
data['last_price'].quantile(q=.25))) &
(data['rooms'] <= data['rooms'].median() +
1.5 * (data['rooms'].quantile(q=.75) -
data['rooms'].quantile(q=.25)))
].groupby('rooms')['last_price'].mean().plot(
xticks=[n + 1 for n in range(5)],
figsize=(10, 3))
plt.xlabel('Количество комнат')
plt.ylabel('Средняя стоимость\nобъекта, руб.')
plt.show()
data.plot.scatter(
x='floor_type',
y='last_price',
xlabel='Тип этажа',
ylabel='Цена объекта, руб.',
title='Диаграмма рассеяния\nзначений цены объекта недвижимости' +
'\nпо значениям типа этажа',
alpha=0.2,
figsize=(5, 3))
plt.show()
plt.title('График зависимости\nсредней стоимости объекта недвижимости' +
'\nот типа этажа')
data.groupby('floor_type')['last_price'].mean().plot(figsize=(5, 3))
plt.xlabel('Тип этажа')
plt.ylabel('Средняя стоимость\nобъекта, руб.')
plt.show()
plt.title('График зависимости\nсредней стоимости объекта от типа этажа' +
'\nдля значений, попадающих в размах "усов" на диаграмме размаха')
data.loc[data['last_price'] <= data['last_price'].median() +
1.5 * (data['last_price'].quantile(q=.75) -
data['last_price'].quantile(q=.25))
].groupby('floor_type')['last_price'].mean().plot(figsize=(8, 3))
plt.xlabel('Тип этажа')
plt.ylabel('Средняя стоимость\nобъекта, руб.')
plt.show()
data.plot.scatter(
x='weekday',
y='last_price',
xlabel='День недели публикации',
ylabel='Цена объекта, руб.',
title='Диаграмма рассеяния\nзначений цены объекта недвижимости' +
'\nпо значениям дней недели публикации объявления',
alpha=0.2,
figsize=(6, 3))
plt.xticks(np.arange(7), ['пн', 'вт', 'ср', 'чт', 'пт', 'сб', 'вс'])
plt.show()
plt.title('График зависимости' +
'\nсредней стоимости объекта недвижимости от дня недели публикации')
data.groupby('weekday')['last_price'].mean().plot(figsize=(10, 3))
plt.xlabel('День недели публикации')
plt.ylabel('Средняя стоимость\nобъекта, руб.')
plt.xticks(np.arange(7), ['пн', 'вт', 'ср', 'чт', 'пт', 'сб', 'вс'])
plt.show()
plt.title('График зависимости' +
'\nсредней стоимости объекта от дня недели публикации' +
'\nдля значений, попадающих в размах "усов" на диаграмме размаха')
data.loc[data['last_price'] <= data['last_price'].median() +
1.5 * (data['last_price'].quantile(q=.75) -
data['last_price'].quantile(q=.25))
].groupby('weekday')['last_price'].mean().plot(figsize=(10, 3))
plt.xlabel('День недели публикации')
plt.ylabel('Средняя стоимость\nобъекта, руб.')
plt.xticks(np.arange(7), ['пн', 'вт', 'ср', 'чт', 'пт', 'сб', 'вс'])
plt.show()
data.plot.scatter(
x='month',
y='last_price',
xlabel='Месяц публикации',
ylabel='Цена объекта, руб.',
title='Диаграмма рассеяния\nзначений цены объекта недвижимости' +
'\nпо значениям месяца публикации объявления',
xticks=[n + 1 for n in range(12)],
alpha=0.2,
figsize=(6, 3))
plt.show()
plt.title('График зависимости' +
'\nсредней стоимости объекта недвижимости от месяца публикации')
data.groupby('month')['last_price'].mean().plot(
xticks=[n + 1 for n in range(12)],
figsize=(10, 3))
plt.xlabel('Месяц публикации')
plt.ylabel('Средняя стоимость\nобъекта, руб.')
plt.show()
plt.title('График зависимости\nсредней стоимости объекта от месяца публикации' +
'\nдля значений, попадающих в размах "усов" на диаграмме размаха,' +
'\nза период 2015—2018 гг.')
data[(data['last_price'] <= data['last_price'].median() +
1.5 * (data['last_price'].quantile(q=.75) -
data['last_price'].quantile(q=.25))) &
(data['year'] > 2014) & (data['year'] < 2019)
].groupby('month')['last_price'].mean().plot(
xticks=[n + 1 for n in range(12)],
figsize=(10, 3))
plt.xlabel('Месяц публикации')
plt.ylabel('Средняя стоимость\nобъекта, руб.')
plt.show()
data.plot.scatter(
x='year',
y='last_price',
xlabel='Год публикации',
ylabel='Цена объекта, руб.',
title='Диаграмма рассеяния\nзначений цены объекта недвижимости' +
'\nпо значениям года публикации объявлений',
alpha=0.2,
figsize=(6, 3))
plt.show()
plt.title('График зависимости' +
'\nсредней стоимости объекта недвижимости от года публикации')
data.groupby('year')['last_price'].mean().plot(figsize=(10, 3))
plt.xlabel('Год публикации')
plt.ylabel('Средняя стоимость\nобъекта, руб.')
plt.show()
plt.title('График зависимости' +
'\nсредней стоимости объекта недвижимости от года публикации' +
'\nдля значений, попадающих в размах "усов" на диаграмме размаха')
data.loc[data['last_price'] <= data['last_price'].median() +
1.5 * (data['last_price'].quantile(q=.75) -
data['last_price'].quantile(q=.25))
].groupby('year')['last_price'].mean().plot(figsize=(10, 3))
plt.xlabel('Месяц публикации')
plt.ylabel('Средняя стоимость\nобъекта, руб.')
plt.show()
*Характеристики объявлений*
Данные собраны за период 4,5 года — с 27 ноября 2014 г. по 3 мая 2019 г. За это время было опубликовано около 23,5 тыс. объявлений. Причём половину объявлений опубликовали за первые 3 года, а вторую половину — за оставшиеся 1,5 года. Это свидетельствует об увеличении объёма публикаций в единицу времени.
Всего за рассматриваемый период времени в наборе данных находятся объявления, опубликованные в 6 различных календарных годах. В рассматриваемом периоде содержатся полные 4 года — 2015–2018 гг., первая треть 2019 года и последний месяц 2014 года. В 2014 году, когда до конца года оставалось немногим более месяца, было опубликовано всего 134 объявления. В 2015 году было опубликовано 1183 объявления — минимальное число публикуемых объявлений в год. В 2016 году наблюдался рост числа опубликованных почти в 2,5 раза по сравнению с предыдущим годом — до 2762 объявлений. В 2017 году рост продолжился. По сравнению с 2016 годом количество объявлений, опубликованных за год, увеличилось в 3 раза и составило 8112 объявлений. В 2018 году количество опубликованных объявлений осталось почти на таком же уровне, как и годом ранее, — 8403 объявления (рост менее 4 %). За рассматриваемый период это максимальное число объявлений, опубликованных за один год. В 2019 году только за первые четыре месяца было опубликовано примерно такое же количество объявлений, как за весь 2016 год.
В среднем за 4 года — с 2015 по 2018 гг. — количество объявлений, публикуемых в течение года, изменялось неравномерно. Так, меньше всего объявлений публиковалось в январе, больше всего — в ноябре. В феврале количество публикуемых объявлений растёт почти в 2 раза по сравнению с январём. С февраля по май наблюдается снижение, а с мая по июнь наблюдается рост количества публикуемых объявлений. С июня по август количество опубликованных объявлений остаётся на приблизительно одинаковом уровне. С августа по ноябрь наблюдается рост, а с ноября по январь происходит снижение количества публикуемых объявлений. Однако для каждого года наблюдается своя картина распределения количества публикаций объявлений по месяцам.
По дням недели распределение количества публикуемых объявлений тоже неравномерное. Количество публикуемых объявлений в будние дни отличается от количества публикуемых объявлений в выходные: в субботу или воскресенье количество опубликованных объявлений в среднем в два раза меньше, чем в будний день.
Число публикаций объявлений растёт со средней скоростью 10 объявлений в день. Практически всегда число публикаций в день не превышает 50, но не менее 1. Максимальное число объявлений, опубликованных в течение одного дня, составило 359.
На момент получения данных опубликованными остаются 3150 объявлений. 20 289 объявлений к этому моменту были сняты с публикации. Большинство объявлений остаются опубликованными не более одного года. В среднем одно объявление остаётся опубликованным 96 дней (3 месяца). Наиболее частые случаи, когда объявления остаются опубликованными в течение 7, 14, 30, 45, 90 дней.
Почти 20 % всех объявлений снимают с публикации в течение первых 30 дней. Ещё 30 % объявлений остаются опубликованными в течение 30-90 дней. До полугода остаются опубликованными ещё 20 %, до года — ещё 15 %. Оставшиеся 15 % объявлений находились на сайте более одного года. Максимальный период, в течение которого объявление находилось на сайте, составляет 1510 дней (почти 4,5 года).
Из объявлений, продолжающих оставаться опубликованными на сайте, половина их находится на сайте около 3 месяцев. Ещё 30 % объявлений остаются опубликованными в течение года, а оставшиеся 20 % — более года (но не более 2 лет).
Снимать объявления с публикации начали 16 июня 2016 года, до этого дня объявления только публиковались. Из всех снятых с публикации объявлений в период с июня 2016 года по апрель 2018 года (в течение почти 2 лет) была снята половина объявлений, вторая половина объявлений была снята в период с апреля 2018 года по май 2019 года (в течение одного года). Это говорит об увеличении скорости не только публикации, но и снятия объявлений с публикации.
*Характеристики зданий и их местоположений*
Большинство объектов недвижимости (77 %), предлагаемых в объявлениях, расположены в границах города Санкт-Петербурга, что в 3 раза больше, чем количество объектов в Ленинградской области. Число объектов, расположенных в городских населённых пунктах (83 %), в 7 раз больше числа объектов, расположенных в сельских пунктах (13 %).
На сайте предлагают объекты недвижимости, расположенные в 310 населённых пунктах: 286 различных населённых пунктов находится в Ленинградской области. 23 населённых пункта находятся в черте города Санкт-Петербурга. Из всех населённых пунктов на города приходятся только 10 %, а из населённых пунктов Ленинградской области треть являются деревнями и столько же — посёлками. Таким образом, большое количество различных сельских населённых пунктов связано с малым количество выставляемой там на продажу недвижимости. В то же время, в небольшом количестве городских населённых пунктов выставляется на продажу значительное количество объектов недвижимости.
Объекты недвижимости располагаются не ближе 200 м к центру Санкт-Петербурга, но не далее 66 км от центра. В среднем объекты недвижимости располагаются на расстоянии 14 км от центра Санкт-Петербурга. Большинство всех объектов недвижимости расположены на расстоянии 2,6–23,6 км от центра Санкт-Петербурга, это определяется, главным образом, объектами недвижимости, расположенными в черте города Санкт-Петербурга.
Большинство объектов недвижимости расположены от аэропорта Пулково на расстоянии не более 55 км. Самый близко расположенный объект находится на расстоянии 6,4 км от аэропорта. Расстояние до аэропорта от самых далёких объектов недвижимости составляет 85 км. В среднем до аэропорта от объекта недвижимости 29 км.
Не для всех объектов недвижимости известны сведения о расположении в радиусе 3 км парков и водоёмов. Только 77 % объявлений содержат сведения о парках и водоёмах. Все эти объекты расположены в черте города Санкт-Петербурга.
Отношение количества объектов недвижимости, имеющих доступ хотя бы к одному к парку в радиусе 3 км, к количеству объектов недвижимости, не имеющих такового, составляет 5 : 4. Из тех объектов, которые имеют в радиусе 3 км по крайней мере один парк, 70 % имеют только 1 парк, 22 % — 2 парка, 8 % — 3 парка. В среднем расстояние до ближайшего парка составляет 450 м.
Отношение количества объектов недвижимости, имеющих доступ хотя бы к одному водоёму в радиусе 3 км, к количеству объектов недвижимости, не имеющих такового, составляет 1 : 1. Из тех объектов, которые имеют в радиусе 3 км по крайней мере один водоём, 63 % имеют только 1 водоём, 21 % — 2 водоёма, 16 % — 3 водоёма. В среднем расстояние до ближайшего водоёма составляет 500 м.
Все объекты недвижимости расположены в зданиях разной этажности: от 1-этажных до 29-этажных и одно 35-этажное здание — самое высокое в Санкт-Петербурге и Ленинградской области. Чаще всего объявления содержат информацию об объектах недвижимости, расположенных в 5-этажных зданиях (почти четверть всех объявлений — 24,5 %). Кроме того, наибольшее количество объектов недвижимости расположено в зданиях в 9, 12, 16, 25 этажей — среди которых много типовых зданий; также большое количество объявлений содержат сведения об объектах недвижимости, расположенных в 4- и 10-этажных зданиях.
*Характеристики объектов недвижимости*
Четверть всех объектов недвижимости расположено либо на первом, либо на последнем этажах: причём их количество распределено почти поровну (12 % и 14 %, соответственно). Наибольшее число объектов недвижимости расположено с 1 по 5 этажи, включительно. Среди них чаще всего попадаются объекты, расположенных на 2 этаже. Почти в два раза реже встречаются объявления об объектах недвижимости, расположенных на этажах с 6 по 9, включительно. Ещё в два раза реже встречаются объявления об объектах недвижимости, расположенных на этажах с 10 по 12. Ещё более редкие — объекты недвижимости, расположенные на этажах с 12 по 17, включительно, ещё реже встречаются объекты недвижимости, расположенные на этажах с 18 по 25. Практически не встречаются объекты недвижимости, расположенные выше 25 этажа.
Большинство квартир — 1-, 2- или 3-комнатные: на них приходится почти 93 % всех объявлений. Лишь 5 % всех объявлений содержат сведения о 4-комнатных квартирах, а около 2 % объявлений — о квартирах с 5 и более жилыми комнатами. Больше всего предлагают 1- и 2-комнатные квартиры — количество таких объявлений составляет 68 %, и распределены они поровну между 1- и 2-комнатными квартирами. Четверть всех объявлений (25 %) содержит сведения о 3-комнатных квартирах. Большинство квартир не имеют балконов — 64,5 %, только 35,5 % объявлений имеют балконы: в основном, один или два. Менее 2,% % квартир имеют от 3 до 5 балконов.
Общая площадь большинства квартир не превышает 97 м$^2$. В среднем площадь квартир составляет 50 м$^2$. Попадаются объекты недвижимости как с очень маленькими площадами (минимальная общая площадь — 13 м$^2$), так и с очень большими (максимальная общая площадь — 900 м$^2$). При этом жилая площадь не превышает 66 м$^2$. Может изменяться от 6 до 410 м$^2$. Но в среднем составляет 30 м$^2$. Площадь кухни изменяется от 2 до 112 м$^2$. Но большинство объектов недвижимости имеют кухню площадью не более 17 м$^2$. В среднем на кухню приходится 9 м$^2$. Высота потолков в квартирах изменяется от 2 до 6 м. В большинстве квартир высота потолков изменяется от 2,2 до 3 м. Среднее значение высоты потолков оставляет 2,65 м.
В наборе данных редко встречаются квартиры-студии. Только 1 % всех квартир имеют свободную планировку и могу считаться квартирами-студиями. Среди объявлений почти не найти апартаментов. Преимущественно все объекты недвижимости относятся к жилым помещениям. Только 0,2 % всех объектов недвижимости являются апартаментами.
Не все объявления сопровождаются фотографиями объекта недвижимости: 4,5 % квартир не имеют своих изображений. В среднем к объявлению прикладывают 9–10 фотографий. Большинство объектов недвижимости сопровождаются не более 20 фотографиями.
*Финансовые характеристики*
Стоимость большинства объектов недвижимости не превышает 9,69 млн руб. Есть квартиры как с минимальной стоимостью в 12 тыс. руб., так и с максимальной стоимостью в 763 млн руб., что скорее является исключение, нежели правилом. Половина всех предлагаемых квартир стоит 3,44–6,8 млн руб., а в среднем — 4,65 млн руб.
Цена за квадратный метр в среднем составляет 95 тыс. руб. А у половины всех объектов недвижимости цена за квадратный метр изменяется в диапазоне 77–114 тыс. руб. Минимальная цена квадратного метра составляет 112 руб., максимальная — 1,9 млн руб. Самая высокая цена за квадратный метр у объектов недвижимости, расположенных в Санкт-Петербурге, — 110 тыс. руб. Затем следуют объекты недвижимости, расположенные в Кудрово и Мурино — городах-спутниках Санкт-Петербурга. Стоимость квадратного метра там составляет 95 тыс. и 86 тыс. руб. В этих трёх городах предлагается больше всего объектов недвижимости для продажи. Помимо этих городов в топ-10 населённых пунктов по количеству объектов недвижимости для продажи входят (в порядке уменьшения предложения) Всеволожск, Гатчина, Выборг, Новое Девяткино, Сертолово, Кириши и Бугры. Стоимость квадратного метра в этих населённых пунктах изменяется от 39 тыс. до 81 тыс. руб.
В Санкт-Петербурге к продаже предлагалось более 18 тыс. объектов недвижимости. Все они находятся на разном удалении от центра города. Самые дорогие объекты недвижимости расположены в пределах 7 км от центра Санкт-Петербурга: средняя стоимость объектов недвижимости в радиусе 7 км от центра города составляет от 11 до 21 млн руб. В пределах от 10 до 65 км от центра города средняя стоимость объектов недвижимости снижается и составляет около 5 млн руб.
Наибольшее влияние на стоимость объектов недвижимости оказывает размер общей площади. Ожидается прямая положительная зависимость стоимости квартиры от значения общей площади. Значительное влияние на стоимость объектов недвижимости оказывают размер жилой площади, площади кухни и количество жилых комнат. Ожидается также прямая положительная зависимость стоимости квартиры от этих параметров.
Объекты недвижимости, расположенные на первых и последних этажах, как правило, стоят дешевле. Остальные этажи в среднем на 15—20 % дороже. Исключением являются квартиры, расположенные в пентхаусе: у них большая общая площадь, высокие потолки и значительно более высокая цена.
Объявления с самыми дорогими объектами недвижимости публиковали с понедельника по среду, а с самыми дешёвыми — в субботу и воскресенье. Объявления с самыми дорогими объектами недвижимости публиковали в последние три месяца года (октябрь, ноябрь, декабрь), а с самыми дешёвыми — в первые три месяца года (январь, февраль и март) и в июне. А в общем, во вторую половину года публикуются объявления с более дорогими квартирами, чем в первую половину года.
В период с 2014 по 2016 гг. средняя стоимость квартир снизилась почти в два раза. На протяжении 2016–2018 гг. средняя стоимость сохранялась на низком уровне. А уже за первые четыре месяца 2019 года средняя стоимость квартир увеличилась по сравнению с 2018 годом.